From a96fb086294d0a55a3dcece114e095d46fca620b Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Mon, 29 Apr 2013 11:10:13 -0400 Subject: [PATCH 001/306] Added MeshFilters.combine for batching --- CHANGES.md | 6 ++ Source/Core/ComponentDatatype.js | 20 ++-- Source/Core/ExtentTessellator.js | 6 +- Source/Core/MeshFilters.js | 171 +++++++++++++++++++++++++++++++ Source/Renderer/Context.js | 4 +- Source/Scene/CentralBody.js | 6 +- Specs/Core/MeshFiltersSpec.js | 107 +++++++++++++++++++ 7 files changed, 302 insertions(+), 18 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 3b144e1e2126..2b820e7761d7 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -3,6 +3,12 @@ Change Log Beta Releases ------------- + +### TODO + +* Breaking changes: + * Renamed `ComponentDatatype.*.toTypedArray` to `ComponentDatatype.*.createTypedArray`. + ### b16 - 2013-05-01 * Breaking changes: * Removed the color, outline color, and outline width properties of polylines. Instead, use materials for polyline color and outline properties. Code that looked like: diff --git a/Source/Core/ComponentDatatype.js b/Source/Core/ComponentDatatype.js index a8fda60e37c5..77f40103f4de 100644 --- a/Source/Core/ComponentDatatype.js +++ b/Source/Core/ComponentDatatype.js @@ -28,8 +28,8 @@ define(['./Enumeration'], function(Enumeration) { */ ComponentDatatype.BYTE = new Enumeration(0x1400, 'BYTE'); ComponentDatatype.BYTE.sizeInBytes = Int8Array.BYTES_PER_ELEMENT; - ComponentDatatype.BYTE.toTypedArray = function(values) { - return new Int8Array(values); + ComponentDatatype.BYTE.createTypedArray = function(valuesOrLength) { + return new Int8Array(valuesOrLength); }; ComponentDatatype.BYTE.createArrayBufferView = function(buffer, byteOffset) { @@ -45,8 +45,8 @@ define(['./Enumeration'], function(Enumeration) { */ ComponentDatatype.UNSIGNED_BYTE = new Enumeration(0x1401, 'UNSIGNED_BYTE'); ComponentDatatype.UNSIGNED_BYTE.sizeInBytes = Uint8Array.BYTES_PER_ELEMENT; - ComponentDatatype.UNSIGNED_BYTE.toTypedArray = function(values) { - return new Uint8Array(values); + ComponentDatatype.UNSIGNED_BYTE.createTypedArray = function(valuesOrLength) { + return new Uint8Array(valuesOrLength); }; ComponentDatatype.UNSIGNED_BYTE.createArrayBufferView = function(buffer, byteOffset) { @@ -62,8 +62,8 @@ define(['./Enumeration'], function(Enumeration) { */ ComponentDatatype.SHORT = new Enumeration(0x1402, 'SHORT'); ComponentDatatype.SHORT.sizeInBytes = Int16Array.BYTES_PER_ELEMENT; - ComponentDatatype.SHORT.toTypedArray = function(values) { - return new Int16Array(values); + ComponentDatatype.SHORT.createTypedArray = function(valuesOrLength) { + return new Int16Array(valuesOrLength); }; ComponentDatatype.SHORT.createArrayBufferView = function(buffer, byteOffset) { @@ -79,8 +79,8 @@ define(['./Enumeration'], function(Enumeration) { */ ComponentDatatype.UNSIGNED_SHORT = new Enumeration(0x1403, 'UNSIGNED_SHORT'); ComponentDatatype.UNSIGNED_SHORT.sizeInBytes = Uint16Array.BYTES_PER_ELEMENT; - ComponentDatatype.UNSIGNED_SHORT.toTypedArray = function(values) { - return new Uint16Array(values); + ComponentDatatype.UNSIGNED_SHORT.createTypedArray = function(valuesOrLength) { + return new Uint16Array(valuesOrLength); }; ComponentDatatype.UNSIGNED_SHORT.createArrayBufferView = function(buffer, byteOffset) { @@ -96,8 +96,8 @@ define(['./Enumeration'], function(Enumeration) { */ ComponentDatatype.FLOAT = new Enumeration(0x1406, 'FLOAT'); ComponentDatatype.FLOAT.sizeInBytes = Float32Array.BYTES_PER_ELEMENT; - ComponentDatatype.FLOAT.toTypedArray = function(values) { - return new Float32Array(values); + ComponentDatatype.FLOAT.createTypedArray = function(valuesOrLength) { + return new Float32Array(valuesOrLength); }; ComponentDatatype.FLOAT.createArrayBufferView = function(buffer, byteOffset) { diff --git a/Source/Core/ExtentTessellator.js b/Source/Core/ExtentTessellator.js index a3a9a74a5149..cb2983c3d911 100644 --- a/Source/Core/ExtentTessellator.js +++ b/Source/Core/ExtentTessellator.js @@ -291,8 +291,8 @@ define([ * * var datatype = ComponentDatatype.FLOAT; * var usage = BufferUsage.STATIC_DRAW; - * var positionBuffer = context.createVertexBuffer(datatype.toTypedArray(buffers.positions), usage); - * var textureCoordinateBuffer = context.createVertexBuffer(datatype.toTypedArray(buffers.textureCoordinates), usage); + * var positionBuffer = context.createVertexBuffer(datatype.createTypedArray(buffers.positions), usage); + * var textureCoordinateBuffer = context.createVertexBuffer(datatype.createTypedArray(buffers.textureCoordinates), usage); * attributes = [{ * index : attributeIndices.position, * vertexBuffer : positionBuffer, @@ -319,7 +319,7 @@ define([ * * var datatype = ComponentDatatype.FLOAT; * var usage = BufferUsage.STATIC_DRAW; - * var typedArray = datatype.toTypedArray(buffers.vertices); + * var typedArray = datatype.createTypedArray(buffers.vertices); * var buffer = context.createVertexBuffer(typedArray, usage); * var stride = 5 * datatype.sizeInBytes; * var attributes = [{ diff --git a/Source/Core/MeshFilters.js b/Source/Core/MeshFilters.js index 4040b55d7946..96a36bedf60b 100644 --- a/Source/Core/MeshFilters.js +++ b/Source/Core/MeshFilters.js @@ -564,5 +564,176 @@ define([ return mesh; }; + function findAttributesInAllMeshes(meshes) { + var length = meshes.length; + + var attributesInAllMeshes = {}; + + var attributes0 = meshes[0].attributes; + var name; + + for (name in attributes0) { + if (attributes0.hasOwnProperty(name)) { + var attribute = attributes0[name]; + var numberOfComponents = attribute.values.length; + var inAllMeshes = true; + + // Does this same attribute exist in all meshes? + for (var i = 1; i < length; ++i) { + var otherAttribute = meshes[i].attributes[name]; + + if ((typeof otherAttribute === 'undefined') || + (attribute.componentDatatype !== otherAttribute.componentDatatype) || + (attribute.componentsPerAttribute !== otherAttribute.componentsPerAttribute) || + (attribute.normalize !== otherAttribute.normalize)) { + + inAllMeshes = false; + break; + } + + numberOfComponents += otherAttribute.values.length; + } + + if (inAllMeshes) { +// TODO: new type to allocate this + attributesInAllMeshes[name] = { + componentDatatype : attribute.componentDatatype, + componentsPerAttribute : attribute.componentsPerAttribute, + normalize : attribute.normalize, + values : attribute.componentDatatype.createTypedArray(numberOfComponents) + }; + } + } + } + + return attributesInAllMeshes; + } + + /** + * DOC_TBA + * + * @exception {DeveloperError} meshes is required and must have length greater than zero. + */ + MeshFilters.combine = function(meshes) { + if ((typeof meshes === 'undefined') || (meshes.length < 1)) { + throw new DeveloperError('meshes is required.'); + } + + if (meshes.length === 1) { + return meshes[0]; + } + + var length = meshes.length; + var name; + var i; + var j; + var k; + + // Find subset of attributes in all meshes + var attributes = findAttributesInAllMeshes(meshes); + + // PERFORMANCE_IDEA: Interleave here instead of createVertexArrayFromMesh to save a copy. + // This will require adding offset and stride to the mesh. + + // Combine attributes from each mesh into a single typed array + for (name in attributes) { + if (attributes.hasOwnProperty(name)) { + var values = attributes[name].values; + + k = 0; + for (i = 0; i < length; ++i) { + var sourceValues = meshes[i].attributes[name].values; + var sourceValuesLength = sourceValues.length; + + for (j = 0; j < sourceValuesLength; ++j) { + values[k++] = sourceValues[j]; + } + } + } + } + + // Combine index lists + + // First, determine the size of a typed array per primitive type + var numberOfIndices = {}; + var indexLists; + var indexListsLength; + var indices; + + for (i = 0; i < length; ++i) { + indexLists = meshes[i].indexLists; + indexListsLength = indexLists.length; + + for (j = 0; j < indexListsLength; ++j) { + indices = indexLists[j]; + + numberOfIndices[indices.primitiveType] = (typeof numberOfIndices[indices.primitiveType] !== 'undefined') ? + (numberOfIndices[indices.primitiveType] += indices.values.length) : indices.values.length; + } + } + + // Next, allocate a typed array for indices per primitive type + var combinedIndexLists = []; + var indexListsByPrimitiveType = {}; + + for (name in numberOfIndices) { + if (numberOfIndices.hasOwnProperty(name)) { + var num = numberOfIndices[name]; + + if (num < 60 * 1024) { + values = new Uint16Array(num); + } else { + values = new Uint32Array(num); + } + + combinedIndexLists.push({ +// TODO: Explicit type for this + primitiveType : PrimitiveType[name], + values : values + }); + + indexListsByPrimitiveType[name] = { + values : values, + currentOffset : 0 + }; + } + } + + // Finally, combine index lists with the same primitive type + var offset = 0; + + for (i = 0; i < length; ++i) { + indexLists = meshes[i].indexLists; + indexListsLength = indexLists.length; + + for (j = 0; j < indexListsLength; ++j) { + var indices = indexLists[j]; + var sourceValues = indices.values; + var sourceValuesLength = sourceValues.length; + var destValues = indexListsByPrimitiveType[indices.primitiveType].values; + var m = indexListsByPrimitiveType[indices.primitiveType].currentOffset; + + for (k = 0; k < sourceValuesLength; ++k) { + destValues[m++] = offset + sourceValues[k]; + } + + indexListsByPrimitiveType[indices.primitiveType].currentOffset = m; + } + + var attrs = meshes[i].attributes; + for (name in attrs) { + if (attrs.hasOwnProperty(name)) { + offset += attrs[name].values.length / attrs[name].componentsPerAttribute; + break; + } + } + } + + return { + attributes : attributes, + indexLists : combinedIndexLists + }; + }; + return MeshFilters; }); diff --git a/Source/Renderer/Context.js b/Source/Renderer/Context.js index ac1921261c61..33b755d409eb 100644 --- a/Source/Renderer/Context.js +++ b/Source/Renderer/Context.js @@ -2193,7 +2193,7 @@ define([ var sizeInBytes = attributes[name].componentDatatype.sizeInBytes; views[name] = { - pointer : attributes[name].componentDatatype.toTypedArray(buffer), + pointer : attributes[name].componentDatatype.createTypedArray(buffer), index : offsetsInBytes[name] / sizeInBytes, // Offset in ComponentType strideInComponentType : vertexSizeInBytes / sizeInBytes }; @@ -2283,7 +2283,7 @@ define([ attribute = attributes[name]; vaAttributes.push({ index : attributeIndices[name], - vertexBuffer : attribute.values ? this.createVertexBuffer(attribute.componentDatatype.toTypedArray(attribute.values), bufferUsage) : undefined, + vertexBuffer : attribute.values ? this.createVertexBuffer(attribute.componentDatatype.createTypedArray(attribute.values), bufferUsage) : undefined, value : attribute.value ? attribute.value : undefined, componentDatatype : attribute.componentDatatype, componentsPerAttribute : attribute.componentsPerAttribute, diff --git a/Source/Scene/CentralBody.js b/Source/Scene/CentralBody.js index b5d02782c3fa..9852ec63f707 100644 --- a/Source/Scene/CentralBody.js +++ b/Source/Scene/CentralBody.js @@ -409,7 +409,7 @@ define([ }); } else { datatype = ComponentDatatype.FLOAT; - this._northPoleCommand.vertexArray.getAttribute(0).vertexBuffer.copyFromArrayView(datatype.toTypedArray(positions)); + this._northPoleCommand.vertexArray.getAttribute(0).vertexBuffer.copyFromArrayView(datatype.createTypedArray(positions)); } } } @@ -457,7 +457,7 @@ define([ }); } else { datatype = ComponentDatatype.FLOAT; - this._southPoleCommand.vertexArray.getAttribute(0).vertexBuffer.copyFromArrayView(datatype.toTypedArray(positions)); + this._southPoleCommand.vertexArray.getAttribute(0).vertexBuffer.copyFromArrayView(datatype.createTypedArray(positions)); } } } @@ -593,7 +593,7 @@ define([ }); } else { var datatype = ComponentDatatype.FLOAT; - this._depthCommand.vertexArray.getAttribute(0).vertexBuffer.copyFromArrayView(datatype.toTypedArray(depthQuad)); + this._depthCommand.vertexArray.getAttribute(0).vertexBuffer.copyFromArrayView(datatype.createTypedArray(depthQuad)); } var shaderCache = context.getShaderCache(); diff --git a/Specs/Core/MeshFiltersSpec.js b/Specs/Core/MeshFiltersSpec.js index d2b99cebc219..e825b56d55ea 100644 --- a/Specs/Core/MeshFiltersSpec.js +++ b/Specs/Core/MeshFiltersSpec.js @@ -492,4 +492,111 @@ defineSuite([ }).toThrow(); }); + it('MeshFilters.combine combines one mesh', function() { + var mesh = { + attributes : { + position : { + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : [0.0, 0.0, 0.0] + } + } + }; + + var combinedMesh = MeshFilters.combine([mesh]); + expect(combinedMesh).toBe(mesh); + }); + + it('MeshFilters.combine combines several meshes', function() { + var mesh = { + attributes : { + position : { + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : [ + 0.0, 0.0, 0.0, + 1.0, 1.0, 1.0, + 2.0, 2.0, 2.0 + ] + }, + normal : { + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : [ + 0.0, 0.0, 0.0, + 1.0, 1.0, 1.0, + 2.0, 2.0, 2.0 + ] + } + }, + indexLists : [{ + primitiveType : PrimitiveType.TRIANGLES, + values : [0, 1, 2] + }, { + primitiveType : PrimitiveType.LINES, + values : [1, 2] + }] + }; + var anotherMesh = { + attributes : { + position : { + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : [ + 3.0, 3.0, 3.0, + 4.0, 4.0, 4.0, + 5.0, 5.0, 5.0 + ] + } + }, + indexLists : [{ + primitiveType : PrimitiveType.TRIANGLES, + values : [0, 1, 2] + }, { + primitiveType : PrimitiveType.POINTS, + values : [0, 1, 2] + }] + }; + + var combinedMesh = MeshFilters.combine([mesh, anotherMesh]); + expect(combinedMesh).toEqual({ + attributes : { + position : { + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : new Float32Array([ + 0.0, 0.0, 0.0, + 1.0, 1.0, 1.0, + 2.0, 2.0, 2.0, + 3.0, 3.0, 3.0, + 4.0, 4.0, 4.0, + 5.0, 5.0, 5.0 + ]) + } + }, + indexLists : [{ + primitiveType : PrimitiveType.TRIANGLES, + values : new Uint16Array([0, 1, 2, 3, 4, 5]) + }, { + primitiveType : PrimitiveType.LINES, + values : new Uint16Array([1, 2]) + }, { + primitiveType : PrimitiveType.POINTS, + values : new Uint16Array([3, 4, 5]) + }] + }); + }); + + it('MeshFilters.combine throws with meshes', function() { + expect(function() { + MeshFilters.combine(); + }).toThrow(); + }); + + it('MeshFilters.combine throws when meshes.length is zero', function() { + expect(function() { + MeshFilters.combine([]); + }).toThrow(); + }); + }); \ No newline at end of file From 52c6ddff44aa150190bc5ccd01e87e9861cb1e89 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Mon, 29 Apr 2013 11:21:57 -0400 Subject: [PATCH 002/306] Added batching to polygons with holes --- CHANGES.md | 2 ++ Source/Core/MeshFilters.js | 2 ++ Source/Scene/Polygon.js | 58 ++++++++++++++++++-------------------- 3 files changed, 31 insertions(+), 31 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 2b820e7761d7..aade2cdd1dab 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -8,6 +8,8 @@ Beta Releases * Breaking changes: * Renamed `ComponentDatatype.*.toTypedArray` to `ComponentDatatype.*.createTypedArray`. +* Improved the performance of drawing polygons created with `configureFromPolygonHierarchy`. +* Added `MeshFilters.combine` to combine meshes for better batching. ### b16 - 2013-05-01 * Breaking changes: diff --git a/Source/Core/MeshFilters.js b/Source/Core/MeshFilters.js index 96a36bedf60b..a6aab52b1f32 100644 --- a/Source/Core/MeshFilters.js +++ b/Source/Core/MeshFilters.js @@ -652,6 +652,8 @@ define([ } } + // PERFORMANCE_IDEA: Could combine with fitToUnsignedShortIndices, but it would start to get ugly. + // Combine index lists // First, determine the size of a typed array per primitive type diff --git a/Source/Scene/Polygon.js b/Source/Scene/Polygon.js index 5d7c7e7a0054..ffe7481cd113 100644 --- a/Source/Scene/Polygon.js +++ b/Source/Scene/Polygon.js @@ -601,44 +601,40 @@ define([ return undefined; } - var processedMeshes = []; - for (i = 0; i < meshes.length; i++) { - mesh = meshes[i]; - mesh = PolygonPipeline.scaleToGeodeticHeight(mesh, polygon.height, polygon.ellipsoid); - mesh = MeshFilters.reorderForPostVertexCache(mesh); - mesh = MeshFilters.reorderForPreVertexCache(mesh); - - if (polygon._mode === SceneMode.SCENE3D) { - mesh.attributes.position2DHigh = { // Not actually used in shader - value : [0.0, 0.0] - }; - mesh.attributes.position2DLow = { // Not actually used in shader - value : [0.0, 0.0] - }; - mesh = MeshFilters.encodeAttribute(mesh, 'position', 'position3DHigh', 'position3DLow'); - } else { - mesh = MeshFilters.projectTo2D(mesh, polygon._projection); - - if ((i === 0) && (polygon._mode !== SceneMode.SCENE3D)) { - var projectedPositions = mesh.attributes.position2D.values; - var positions = []; + mesh = MeshFilters.combine(meshes); + mesh = PolygonPipeline.scaleToGeodeticHeight(mesh, polygon.height, polygon.ellipsoid); + mesh = MeshFilters.reorderForPostVertexCache(mesh); + mesh = MeshFilters.reorderForPreVertexCache(mesh); + + if (polygon._mode === SceneMode.SCENE3D) { + mesh.attributes.position2DHigh = { // Not actually used in shader + value : [0.0, 0.0] + }; + mesh.attributes.position2DLow = { // Not actually used in shader + value : [0.0, 0.0] + }; + mesh = MeshFilters.encodeAttribute(mesh, 'position', 'position3DHigh', 'position3DLow'); + } else { + mesh = MeshFilters.projectTo2D(mesh, polygon._projection); - for (var j = 0; j < projectedPositions.length; j += 2) { - positions.push(new Cartesian3(projectedPositions[j], projectedPositions[j + 1], 0.0)); - } + if (polygon._mode !== SceneMode.SCENE3D) { + var projectedPositions = mesh.attributes.position2D.values; + var positions = []; - polygon._boundingVolume2D = BoundingSphere.fromPoints(positions, polygon._boundingVolume2D); - var center2DPositions = polygon._boundingVolume2D.center; - polygon._boundingVolume2D.center = new Cartesian3(0.0, center2DPositions.x, center2DPositions.y); + for (var j = 0; j < projectedPositions.length; j += 2) { + positions.push(new Cartesian3(projectedPositions[j], projectedPositions[j + 1], 0.0)); } - mesh = MeshFilters.encodeAttribute(mesh, 'position3D', 'position3DHigh', 'position3DLow'); - mesh = MeshFilters.encodeAttribute(mesh, 'position2D', 'position2DHigh', 'position2DLow'); + polygon._boundingVolume2D = BoundingSphere.fromPoints(positions, polygon._boundingVolume2D); + var center2DPositions = polygon._boundingVolume2D.center; + polygon._boundingVolume2D.center = new Cartesian3(0.0, center2DPositions.x, center2DPositions.y); } - processedMeshes = processedMeshes.concat(MeshFilters.fitToUnsignedShortIndices(mesh)); + + mesh = MeshFilters.encodeAttribute(mesh, 'position3D', 'position3DHigh', 'position3DLow'); + mesh = MeshFilters.encodeAttribute(mesh, 'position2D', 'position2DHigh', 'position2DLow'); } - return processedMeshes; + return MeshFilters.fitToUnsignedShortIndices(mesh); } function getGranularity(polygon, mode) { From bf91c815267ff46682789790666a55bdfc22ad90 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Tue, 30 Apr 2013 09:14:32 -0400 Subject: [PATCH 003/306] Minor Polygon.js cleanup --- Source/Scene/Polygon.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Source/Scene/Polygon.js b/Source/Scene/Polygon.js index ffe7481cd113..491fb7bd2a99 100644 --- a/Source/Scene/Polygon.js +++ b/Source/Scene/Polygon.js @@ -468,9 +468,6 @@ define([ var rotation = Quaternion.fromAxisAngle(tangentPlane._plane.normal, angle, appendTextureCoordinatesQuaternion); var textureMatrix = Matrix3.fromQuaternion(rotation, appendTextureCoordinatesMatrix3); - // PERFORMANCE_IDEA: Instead of storing texture coordinates per-vertex, we could - // save memory by computing them in the fragment shader. However, projecting - // the point onto the plane may have precision issues. for ( var i = 0; i < length; i += 3) { var p = appendTextureCoordinatesCartesian3; p.x = positions[i]; @@ -566,7 +563,10 @@ define([ var mesh; if ((typeof polygon._extent !== 'undefined') && !polygon._extent.isEmpty()) { - meshes.push(ExtentTessellator.compute({extent: polygon._extent, generateTextureCoordinates:true})); + meshes.push(ExtentTessellator.compute({ + extent : polygon._extent, + generateTextureCoordinates : true + })); polygon._boundingVolume = BoundingSphere.fromExtent3D(polygon._extent, polygon._ellipsoid, polygon._boundingVolume); if (polygon._mode !== SceneMode.SCENE3D) { @@ -736,7 +736,7 @@ define([ var commands; var command; - var materialChanged = this._material !== this.material; + var materialChanged = (this._material !== this.material); this._commandLists.removeAll(); if (pass.color) { From e188838d8957af1856c89193a26fe16efb456f66 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Wed, 1 May 2013 17:55:46 -0400 Subject: [PATCH 004/306] Start of generic primitive and appearance --- Apps/CesiumViewer/CesiumViewer.js | 30 +++++++ Source/Scene/Appearance.js | 68 ++++++++++++++ Source/Scene/EllipsoidPrimitive.js | 2 - Source/Scene/Primitive.js | 112 ++++++++++++++++++++++++ Source/Shaders/DefaultAppearanceFS.glsl | 7 ++ Source/Shaders/DefaultAppearanceVS.glsl | 6 ++ 6 files changed, 223 insertions(+), 2 deletions(-) create mode 100644 Source/Scene/Appearance.js create mode 100644 Source/Scene/Primitive.js create mode 100644 Source/Shaders/DefaultAppearanceFS.glsl create mode 100644 Source/Shaders/DefaultAppearanceVS.glsl diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index e9af113d723a..c1c48d02cb3c 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -5,6 +5,12 @@ define([ 'dojo/io-query', 'dojo/parser', 'dojo/ready', + 'Core/Math', + 'Core/Extent', + 'Core/ExtentTessellator', + 'Core/MeshFilters', + 'Scene/Primitive', + 'Scene/Appearance', 'Widgets/Dojo/checkForChromeFrame', 'Widgets/Dojo/CesiumViewerWidget' ], function( @@ -13,6 +19,12 @@ define([ ioQuery, parser, ready, + CesiumMath, + Extent, + ExtentTessellator, + MeshFilters, + Primitive, + Appearance, checkForChromeFrame, CesiumViewerWidget) { "use strict"; @@ -36,6 +48,24 @@ define([ widget.startup(); widget.fullscreen.viewModel.fullscreenElement(document.body); + var mesh = ExtentTessellator.compute({ + extent : new Extent( + CesiumMath.toRadians(-180.0), + CesiumMath.toRadians(50.0), + CesiumMath.toRadians(180.0), + CesiumMath.toRadians(90.0)) + }); + var anotherMesh = ExtentTessellator.compute({ + extent : new Extent( + CesiumMath.toRadians(-180.0), + CesiumMath.toRadians(10.0), + CesiumMath.toRadians(180.0), + CesiumMath.toRadians(30.0)) + }); + + var primitive = new Primitive(MeshFilters.combine([mesh, anotherMesh]), Appearance.EXAMPLE_APPEARANCE); + widget.scene.getPrimitives().add(primitive); + domClass.remove(win.body(), 'loading'); }); }); \ No newline at end of file diff --git a/Source/Scene/Appearance.js b/Source/Scene/Appearance.js new file mode 100644 index 000000000000..7b9ea9b7d8ae --- /dev/null +++ b/Source/Scene/Appearance.js @@ -0,0 +1,68 @@ +/*global define*/ +define([ + '../Core/freezeObject', + '../Renderer/CullFace', + '../Renderer/BlendingState', + './Material', + '../Shaders/DefaultAppearanceVS', + '../Shaders/DefaultAppearanceFS' + ], function( + freezeObject, + CullFace, + BlendingState, + Material, + DefaultAppearanceVS, + DefaultAppearanceFS) { + "use strict"; + + /** + * DOC_TBA + */ + var Appearance = function(options) { +// TODO: throw without options + /** + * DOC_TBA + */ + this.material = options.material; + + /** + * DOC_TBA + */ + this.vertexShaderSource = options.vertexShaderSource; + + /** + * DOC_TBA + */ + this.fragmentShaderSource = options.fragmentShaderSource; + + /** + * DOC_TBA + */ + this.renderState = options.renderState; + }; + + /** + * DOC_TBA + */ + Appearance.prototype.getFragmentShaderSource = function() { + return '#line 0\n' + + this.material.shaderSource + + '#line 0\n' + + this.fragmentShaderSource; + }; + + Appearance.EXAMPLE_APPEARANCE = freezeObject(new Appearance({ + material : Material.fromType(undefined, Material.ColorType), + vertexShaderSource : DefaultAppearanceVS, + fragmentShaderSource : DefaultAppearanceFS, + renderState : { + cull : { + enabled : true, + face : CullFace.BACK + }, + blending : BlendingState.ALPHA_BLEND + } + })); + + return Appearance; +}); \ No newline at end of file diff --git a/Source/Scene/EllipsoidPrimitive.js b/Source/Scene/EllipsoidPrimitive.js index 531a4b81276b..c7f493ea8a03 100644 --- a/Source/Scene/EllipsoidPrimitive.js +++ b/Source/Scene/EllipsoidPrimitive.js @@ -3,7 +3,6 @@ define([ '../Core/BoxTessellator', '../Core/Cartesian3', '../Core/Cartesian4', - '../Core/Color', '../Core/combine', '../Core/ComponentDatatype', '../Core/DeveloperError', @@ -27,7 +26,6 @@ define([ BoxTessellator, Cartesian3, Cartesian4, - Color, combine, ComponentDatatype, DeveloperError, diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js new file mode 100644 index 000000000000..c986dc290523 --- /dev/null +++ b/Source/Scene/Primitive.js @@ -0,0 +1,112 @@ +/*global define*/ +define([ + '../Core/destroyObject', + '../Core/Matrix4', + '../Core/MeshFilters', + '../Core/PrimitiveType', + '../Renderer/BufferUsage', + '../Renderer/VertexLayout', + '../Renderer/CommandLists', + '../Renderer/DrawCommand', + './SceneMode' + ], function( + destroyObject, + Matrix4, + MeshFilters, + PrimitiveType, + BufferUsage, + VertexLayout, + CommandLists, + DrawCommand, + SceneMode) { + "use strict"; + + /** + * DOC_TBA + */ + var Primitive = function(mesh, appearance) { + /** + * DOC_TBA + */ + this.mesh = mesh; + + /** + * DOC_TBA + */ + this.appearance = appearance; + + /** + * DOC_TBA + */ + this.modelMatrix = Matrix4.IDENTITY.clone(); + + /** + * DOC_TBA + */ + this.show = true; + + this._sp = undefined; + this._rs = undefined; + this._va = undefined; + this._commandLists = new CommandLists(); + }; + + /** + * @private + */ + Primitive.prototype.update = function(context, frameState, commandList) { + if (!this.show || (frameState.mode !== SceneMode.SCENE3D)) { +// TODO: support Columbus view and 2D + return; + } + +// TODO: throw if mesh and appearance are not defined + + if (typeof this._va === 'undefined') { + var attributeIndices = MeshFilters.createAttributeIndices(this.mesh); + var appearance = this.appearance; + + this._va = context.createVertexArrayFromMesh({ + mesh : this.mesh, + attributeIndices : attributeIndices, + bufferUsage : BufferUsage.STATIC_DRAW, + vertexLayout : VertexLayout.INTERLEAVED + }); + this._sp = context.getShaderCache().replaceShaderProgram(this._sp, appearance.vertexShaderSource, appearance.getFragmentShaderSource(), attributeIndices); + this._rs = context.createRenderState(appearance.renderState); + + var colorCommand = new DrawCommand(); +// TODO: primitive type from mesh + colorCommand.primitiveType = PrimitiveType.TRIANGLES; + colorCommand.vertexArray = this._va; + colorCommand.renderState = this._rs; + colorCommand.shaderProgram = this._sp; + colorCommand.uniformMap = appearance.material._uniforms; +// TODO: colorCommand.boundingVolume = + colorCommand.modelMatrix = this.modelMatrix; + this._commandLists.colorList.push(colorCommand); + } + + if (frameState.passes.color) { + commandList.push(this._commandLists); + } + }; + + /** + * DOC_TBA + */ + Primitive.prototype.isDestroyed = function() { + return false; + }; + + /** + * DOC_TBA + */ + Primitive.prototype.destroy = function() { + this._sp = this._sp && this._sp.release(); + this._va = this._va && this._va.release(); + return destroyObject(this); + }; + + return Primitive; +}); \ No newline at end of file diff --git a/Source/Shaders/DefaultAppearanceFS.glsl b/Source/Shaders/DefaultAppearanceFS.glsl new file mode 100644 index 000000000000..478683d7b721 --- /dev/null +++ b/Source/Shaders/DefaultAppearanceFS.glsl @@ -0,0 +1,7 @@ +void main() +{ + czm_materialInput materialInput; + + czm_material material = czm_getMaterial(materialInput); + gl_FragColor = vec4(material.diffuse + material.emission, material.alpha); +} diff --git a/Source/Shaders/DefaultAppearanceVS.glsl b/Source/Shaders/DefaultAppearanceVS.glsl new file mode 100644 index 000000000000..971641636b49 --- /dev/null +++ b/Source/Shaders/DefaultAppearanceVS.glsl @@ -0,0 +1,6 @@ +attribute vec4 position; + +void main() +{ + gl_Position = czm_modelViewProjection * position; +} From 43e3f03212b288c6a07bb3cd714aa8e8adeae323 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Wed, 8 May 2013 15:22:42 -0400 Subject: [PATCH 005/306] Fixed destroying vertex array --- Source/Scene/Primitive.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index c986dc290523..7d6b4636449f 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -104,7 +104,7 @@ define([ */ Primitive.prototype.destroy = function() { this._sp = this._sp && this._sp.release(); - this._va = this._va && this._va.release(); + this._va = this._va && this._va.destroy(); return destroyObject(this); }; From a363bc5d1323dab7bb27fa4a5df4207b0bbdb0ba Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Wed, 8 May 2013 15:59:01 -0400 Subject: [PATCH 006/306] Fixed modelMatrix in generic primitive --- Source/Scene/Primitive.js | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index 7d6b4636449f..fd906a8ca7a6 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -48,6 +48,8 @@ define([ this._sp = undefined; this._rs = undefined; this._va = undefined; + + this._commands = []; this._commandLists = new CommandLists(); }; @@ -75,19 +77,24 @@ define([ this._sp = context.getShaderCache().replaceShaderProgram(this._sp, appearance.vertexShaderSource, appearance.getFragmentShaderSource(), attributeIndices); this._rs = context.createRenderState(appearance.renderState); - var colorCommand = new DrawCommand(); -// TODO: primitive type from mesh - colorCommand.primitiveType = PrimitiveType.TRIANGLES; - colorCommand.vertexArray = this._va; - colorCommand.renderState = this._rs; - colorCommand.shaderProgram = this._sp; - colorCommand.uniformMap = appearance.material._uniforms; -// TODO: colorCommand.boundingVolume = - colorCommand.modelMatrix = this.modelMatrix; - this._commandLists.colorList.push(colorCommand); + var command = new DrawCommand(); +// TODO: this assumes indices in the mesh - and only one set + command.primitiveType = this.mesh.indexLists[0].primitiveType; + command.vertexArray = this._va; + command.renderState = this._rs; + command.shaderProgram = this._sp; + command.uniformMap = appearance.material._uniforms; +// TODO: command.boundingVolume = + this._commands.push(command); } if (frameState.passes.color) { + var commands = this._commands; + var len = commands.length; + for (var i = 0; i < len; ++i) { + commands[i].modelMatrix = this.modelMatrix; + this._commandLists.colorList[i] = commands[i]; + } commandList.push(this._commandLists); } }; From fafc2476d500037f089637a4e84578f0783f354e Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Wed, 8 May 2013 18:06:17 -0400 Subject: [PATCH 007/306] Added geometry types --- Source/Core/Geometry.js | 29 ++++++++++++++ Source/Core/GeometryAttribute.js | 39 +++++++++++++++++++ Source/Core/GeometryIndices.js | 29 ++++++++++++++ Source/Core/MeshFilters.js | 61 ++++++++++++++++------------- Source/Scene/Primitive.js | 6 ++- Specs/Core/MeshFiltersSpec.js | 66 +++++++++++++++++--------------- 6 files changed, 172 insertions(+), 58 deletions(-) create mode 100644 Source/Core/Geometry.js create mode 100644 Source/Core/GeometryAttribute.js create mode 100644 Source/Core/GeometryIndices.js diff --git a/Source/Core/Geometry.js b/Source/Core/Geometry.js new file mode 100644 index 000000000000..5d94119918a3 --- /dev/null +++ b/Source/Core/Geometry.js @@ -0,0 +1,29 @@ +/*global define*/ +define(function() { + "use strict"; + + /** + * DOC_TBA + * + * @alias Geometry + * @constructor + */ + var Geometry = function(options) { + /** + * DOC_TBA + */ + this.attributes = options.attributes; + + /** + * DOC_TBA + */ + this.indexLists = options.indexLists; + + /** + * DOC_TBA + */ + this.boundingSphere = options.boundingSphere; + }; + + return Geometry; +}); diff --git a/Source/Core/GeometryAttribute.js b/Source/Core/GeometryAttribute.js new file mode 100644 index 000000000000..b6f3e17119cf --- /dev/null +++ b/Source/Core/GeometryAttribute.js @@ -0,0 +1,39 @@ +/*global define*/ +define([ + './defaultValue' + ], function( + defaultValue) { + "use strict"; + + /** + * DOC_TBA + * + * @alias GeometryAttribute + * @constructor + */ + var GeometryAttribute = function(options) { + options = defaultValue(options, defaultValue.EMPTY_OBJECT); + + /** + * DOC_TBA + */ + this.componentDatatype = options.componentDatatype; + + /** + * DOC_TBA + */ + this.componentsPerAttribute = options.componentsPerAttribute; + + /** + * DOC_TBA + */ + this.normalize = defaultValue(options.normalize, false); + + /** + * DOC_TBA + */ + this.values = options.values; + }; + + return GeometryAttribute; +}); diff --git a/Source/Core/GeometryIndices.js b/Source/Core/GeometryIndices.js new file mode 100644 index 000000000000..fd9e5d9e59c4 --- /dev/null +++ b/Source/Core/GeometryIndices.js @@ -0,0 +1,29 @@ +/*global define*/ +define([ + './defaultValue' + ], function( + defaultValue) { + "use strict"; + + /** + * DOC_TBA + * + * @alias GeometryIndices + * @constructor + */ + var GeometryIndices = function(options) { + options = defaultValue(options, defaultValue.EMPTY_OBJECT); + + /** + * DOC_TBA + */ + this.primitiveType = options.primitiveType; + + /** + * DOC_TBA + */ + this.values = options.values; + }; + + return GeometryIndices; +}); diff --git a/Source/Core/MeshFilters.js b/Source/Core/MeshFilters.js index a6aab52b1f32..851cbee98d25 100644 --- a/Source/Core/MeshFilters.js +++ b/Source/Core/MeshFilters.js @@ -7,7 +7,10 @@ define([ './GeographicProjection', './ComponentDatatype', './PrimitiveType', - './Tipsify' + './Tipsify', + './Geometry', + './GeometryAttribute', + './GeometryIndices' ], function( defaultValue, DeveloperError, @@ -16,7 +19,10 @@ define([ GeographicProjection, ComponentDatatype, PrimitiveType, - Tipsify) { + Tipsify, + Geometry, + GeometryAttribute, + GeometryIndices) { "use strict"; /** @@ -37,7 +43,7 @@ define([ *

* This filter is commonly used to create a wireframe mesh for visual debugging. * - * @param {Object} mesh The mesh to filter, which is modified in place. + * @param {Geometry} mesh The mesh to filter, which is modified in place. * * @returns The modified mesh argument, with its triangle indices converted to lines. * @@ -186,7 +192,7 @@ define([ * The mesh argument should use the standard layout like the mesh returned by {@link BoxTessellator}. *

- * @param {Object} mesh The mesh to filter, which is modified in place. + * @param {Geometry} mesh The mesh to filter, which is modified in place. * * @exception {DeveloperError} All mesh attribute lists must have the same number of attributes. * @@ -271,7 +277,7 @@ define([ * The mesh argument should use the standard layout like the mesh returned by {@link BoxTessellator}. *

- * @param {Object} mesh The mesh to filter, which is modified in place. + * @param {Geometry} mesh The mesh to filter, which is modified in place. * @param {Number} [cacheCapacity=24] The number of vertices that can be held in the GPU's vertex cache. * * @exception {DeveloperError} Mesh's index list must be defined. @@ -305,9 +311,11 @@ define([ maximumIndex = indices[j]; } } - indexLists[i].values = Tipsify.tipsify({indices : indices, - maximumIndex : maximumIndex, - cacheSize : cacheCapacity}); + indexLists[i].values = Tipsify.tipsify({ + indices : indices, + maximumIndex : maximumIndex, + cacheSize : cacheCapacity + }); } } } @@ -329,11 +337,11 @@ define([ for ( var attribute in attributes) { if (attributes.hasOwnProperty(attribute) && attributes[attribute].values) { var attr = attributes[attribute]; - newAttributes[attribute] = { + newAttributes[attribute] = new GeometryAttribute({ componentDatatype : attr.componentDatatype, componentsPerAttribute : attr.componentsPerAttribute, values : [] - }; + }); } } @@ -360,13 +368,13 @@ define([ */ MeshFilters.fitToUnsignedShortIndices = function(mesh) { function createMesh(attributes, primitiveType, indices) { - return { + return new Geometry({ attributes : attributes, - indexLists : [{ + indexLists : [new GeometryIndices({ primitiveType : primitiveType, values : indices - }] - }; + })] + }); } var meshes = []; @@ -498,7 +506,7 @@ define([ * This is commonly used to create high-precision position vertex attributes. *

* - * @param {Object} mesh The mesh to filter, which is modified in place. + * @param {Geometry} mesh The mesh to filter, which is modified in place. * @param {String} [attributeName='position'] The name of the attribute. * @param {String} [attributeHighName='positionHigh'] The name of the attribute for the encoded high bits. * @param {String} [attributeLowName='positionLow'] The name of the attribute for the encoded low bits. @@ -549,16 +557,16 @@ define([ lowValues[i] = encodedResult.low; } - mesh.attributes[attributeHighName] = { + mesh.attributes[attributeHighName] = new GeometryAttribute({ componentDatatype : attribute.componentDatatype, componentsPerAttribute : attribute.componentsPerAttribute, values : highValues - }; - mesh.attributes[attributeLowName] = { + }); + mesh.attributes[attributeLowName] = new GeometryAttribute({ componentDatatype : attribute.componentDatatype, componentsPerAttribute : attribute.componentsPerAttribute, values : lowValues - }; + }); delete mesh.attributes[attributeName]; return mesh; @@ -595,13 +603,12 @@ define([ } if (inAllMeshes) { -// TODO: new type to allocate this - attributesInAllMeshes[name] = { + attributesInAllMeshes[name] = new GeometryAttribute({ componentDatatype : attribute.componentDatatype, componentsPerAttribute : attribute.componentsPerAttribute, normalize : attribute.normalize, values : attribute.componentDatatype.createTypedArray(numberOfComponents) - }; + }); } } } @@ -688,11 +695,10 @@ define([ values = new Uint32Array(num); } - combinedIndexLists.push({ -// TODO: Explicit type for this + combinedIndexLists.push(new GeometryIndices({ primitiveType : PrimitiveType[name], values : values - }); + })); indexListsByPrimitiveType[name] = { values : values, @@ -731,10 +737,11 @@ define([ } } - return { +// TODO: combine bounding spheres + return new Geometry({ attributes : attributes, indexLists : combinedIndexLists - }; + }); }; return MeshFilters; diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index fd906a8ca7a6..e0d6560837a5 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -4,6 +4,7 @@ define([ '../Core/Matrix4', '../Core/MeshFilters', '../Core/PrimitiveType', + '../Core/BoundingSphere', '../Renderer/BufferUsage', '../Renderer/VertexLayout', '../Renderer/CommandLists', @@ -14,6 +15,7 @@ define([ Matrix4, MeshFilters, PrimitiveType, + BoundingSphere, BufferUsage, VertexLayout, CommandLists, @@ -84,7 +86,9 @@ define([ command.renderState = this._rs; command.shaderProgram = this._sp; command.uniformMap = appearance.material._uniforms; -// TODO: command.boundingVolume = +// TODO: make this part of mesh + command.boundingVolume = BoundingSphere.fromVertices(this.mesh.attributes.position.values); + this._commands.push(command); } diff --git a/Specs/Core/MeshFiltersSpec.js b/Specs/Core/MeshFiltersSpec.js index e825b56d55ea..ffe62124016c 100644 --- a/Specs/Core/MeshFiltersSpec.js +++ b/Specs/Core/MeshFiltersSpec.js @@ -8,7 +8,10 @@ defineSuite([ 'Core/Cartesian3', 'Core/EncodedCartesian3', 'Core/Tipsify', - 'Core/GeographicProjection' + 'Core/GeographicProjection', + 'Core/Geometry', + 'Core/GeometryAttribute', + 'Core/GeometryIndices' ], function( MeshFilters, PrimitiveType, @@ -18,7 +21,10 @@ defineSuite([ Cartesian3, EncodedCartesian3, Tipsify, - GeographicProjection) { + GeographicProjection, + Geometry, + GeometryAttribute, + GeometryIndices) { "use strict"; /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/ @@ -493,24 +499,24 @@ defineSuite([ }); it('MeshFilters.combine combines one mesh', function() { - var mesh = { - attributes : { + var mesh = new Geometry({ + attributes : new GeometryAttribute({ position : { componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 3, values : [0.0, 0.0, 0.0] } - } - }; + }) + }); var combinedMesh = MeshFilters.combine([mesh]); expect(combinedMesh).toBe(mesh); }); it('MeshFilters.combine combines several meshes', function() { - var mesh = { + var mesh = new Geometry({ attributes : { - position : { + position : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 3, values : [ @@ -518,8 +524,8 @@ defineSuite([ 1.0, 1.0, 1.0, 2.0, 2.0, 2.0 ] - }, - normal : { + }), + normal : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 3, values : [ @@ -527,19 +533,19 @@ defineSuite([ 1.0, 1.0, 1.0, 2.0, 2.0, 2.0 ] - } + }) }, - indexLists : [{ + indexLists : [new GeometryIndices({ primitiveType : PrimitiveType.TRIANGLES, values : [0, 1, 2] - }, { + }), new GeometryIndices({ primitiveType : PrimitiveType.LINES, values : [1, 2] - }] - }; - var anotherMesh = { + })] + }); + var anotherMesh = new Geometry({ attributes : { - position : { + position : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 3, values : [ @@ -547,21 +553,21 @@ defineSuite([ 4.0, 4.0, 4.0, 5.0, 5.0, 5.0 ] - } + }) }, - indexLists : [{ + indexLists : [new GeometryIndices({ primitiveType : PrimitiveType.TRIANGLES, values : [0, 1, 2] - }, { + }), new GeometryIndices({ primitiveType : PrimitiveType.POINTS, values : [0, 1, 2] - }] - }; + })] + }); var combinedMesh = MeshFilters.combine([mesh, anotherMesh]); - expect(combinedMesh).toEqual({ + expect(combinedMesh).toEqual(new Geometry({ attributes : { - position : { + position : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 3, values : new Float32Array([ @@ -572,19 +578,19 @@ defineSuite([ 4.0, 4.0, 4.0, 5.0, 5.0, 5.0 ]) - } + }) }, - indexLists : [{ + indexLists : [new GeometryIndices({ primitiveType : PrimitiveType.TRIANGLES, values : new Uint16Array([0, 1, 2, 3, 4, 5]) - }, { + }), new GeometryIndices({ primitiveType : PrimitiveType.LINES, values : new Uint16Array([1, 2]) - }, { + }), new GeometryIndices({ primitiveType : PrimitiveType.POINTS, values : new Uint16Array([3, 4, 5]) - }] - }); + })] + })); }); it('MeshFilters.combine throws with meshes', function() { From b01600106002165a6e9c0f999cbc326ff5199946 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Thu, 9 May 2013 07:53:56 -0400 Subject: [PATCH 008/306] Renamed CubeMapEllipsoidTessellator file --- .../{CubeMapEllipsoidTessellator.js => EllipsoidGeometry.js} | 0 ...apEllipsoidTessellatorSpec.js => EllipsoidGeometrySpec.js} | 0 Specs/Core/MeshFiltersSpec.js | 4 ++-- 3 files changed, 2 insertions(+), 2 deletions(-) rename Source/Core/{CubeMapEllipsoidTessellator.js => EllipsoidGeometry.js} (100%) rename Specs/Core/{CubeMapEllipsoidTessellatorSpec.js => EllipsoidGeometrySpec.js} (100%) diff --git a/Source/Core/CubeMapEllipsoidTessellator.js b/Source/Core/EllipsoidGeometry.js similarity index 100% rename from Source/Core/CubeMapEllipsoidTessellator.js rename to Source/Core/EllipsoidGeometry.js diff --git a/Specs/Core/CubeMapEllipsoidTessellatorSpec.js b/Specs/Core/EllipsoidGeometrySpec.js similarity index 100% rename from Specs/Core/CubeMapEllipsoidTessellatorSpec.js rename to Specs/Core/EllipsoidGeometrySpec.js diff --git a/Specs/Core/MeshFiltersSpec.js b/Specs/Core/MeshFiltersSpec.js index ffe62124016c..269768886e7a 100644 --- a/Specs/Core/MeshFiltersSpec.js +++ b/Specs/Core/MeshFiltersSpec.js @@ -3,7 +3,7 @@ defineSuite([ 'Core/MeshFilters', 'Core/PrimitiveType', 'Core/ComponentDatatype', - 'Core/CubeMapEllipsoidTessellator', + 'Core/EllipsoidGeometry', 'Core/Ellipsoid', 'Core/Cartesian3', 'Core/EncodedCartesian3', @@ -16,7 +16,7 @@ defineSuite([ MeshFilters, PrimitiveType, ComponentDatatype, - CubeMapEllipsoidTessellator, + EllipsoidGeometry, Ellipsoid, Cartesian3, EncodedCartesian3, From 9658535d3e357290534f25bb47bee2f5e2417e84 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Thu, 9 May 2013 08:29:59 -0400 Subject: [PATCH 009/306] Renamed CubeMapEllipsoidTessellator to SphereGeometry. Changed from static function to object. --- CHANGES.md | 3 ++ Source/Core/BoundingSphere.js | 18 ++++++++ Source/Core/BoxTessellator.js | 2 +- Source/Core/EllipsoidGeometry.js | 71 ++++++++++++++++------------- Source/Core/ExtentTessellator.js | 2 +- Source/Core/Geometry.js | 7 ++- Source/Core/HeightmapTessellator.js | 2 +- Source/Core/MeshFilters.js | 4 +- Source/Core/PlaneTessellator.js | 2 +- Source/Scene/CentralBody.js | 2 - Source/Scene/CentralBodySurface.js | 6 +-- Source/Scene/Primitive.js | 4 +- Source/Scene/SkyAtmosphere.js | 6 +-- Specs/Core/EllipsoidGeometrySpec.js | 13 +++--- Specs/Core/MeshFiltersSpec.js | 2 +- 15 files changed, 88 insertions(+), 56 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index a0c64085a01e..93f881131568 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -7,10 +7,13 @@ Beta Releases ### b17 - 2013-06-03 * Breaking changes: + * Replaced tessellators and meshes with geometry. In particular: + * Replaced `CubeMapEllipsoidTessellator` with `EllipsoidGeometry`. * Renamed `ComponentDatatype.*.toTypedArray` to `ComponentDatatype.*.createTypedArray`. * Replaced `Uniform.getFrameNumber` and `Uniform.getTime` with `Uniform.getFrameState`, which returns the full frame state. * Improved the performance of drawing polygons created with `configureFromPolygonHierarchy`. * Added `MeshFilters.combine` to combine meshes for better batching. +* Added `BoundingSphere.fromEllipsoid`. * Added `DrawCommand.cull` to avoid redundant visibility checks. * Added `czm_morphTime` automatic GLSL uniform. * Added support for floating-point textures. diff --git a/Source/Core/BoundingSphere.js b/Source/Core/BoundingSphere.js index a6d0d59e1152..abac452e7466 100644 --- a/Source/Core/BoundingSphere.js +++ b/Source/Core/BoundingSphere.js @@ -523,6 +523,24 @@ define([ return result; }; + /** + * DOC_TBA + * + * @exception {DeveloperError} ellipsoid is required. + */ + BoundingSphere.fromEllipsoid = function(ellipsoid, result) { + if (typeof ellipsoid === 'undefined') { + throw new DeveloperError('ellipsoid is required.'); + } + + if (typeof result === 'undefined') { + result = new BoundingSphere(); + } + + result.radius = ellipsoid.getMaximumRadius(); + return result; + }; + /** * Duplicates a BoundingSphere instance. * @memberof BoundingSphere diff --git a/Source/Core/BoxTessellator.js b/Source/Core/BoxTessellator.js index 3e96251b0457..3a9bfb7c13a5 100644 --- a/Source/Core/BoxTessellator.js +++ b/Source/Core/BoxTessellator.js @@ -19,7 +19,7 @@ define([ * @alias BoxTessellator * @exports BoxTessellator * - * @see CubeMapEllipsoidTessellator + * @see EllipsoidGeometry * @see PlaneTessellator */ var BoxTessellator = { diff --git a/Source/Core/EllipsoidGeometry.js b/Source/Core/EllipsoidGeometry.js index 56d5d7a5d3a4..dc7dc9d06dd3 100644 --- a/Source/Core/EllipsoidGeometry.js +++ b/Source/Core/EllipsoidGeometry.js @@ -4,40 +4,36 @@ define([ './DeveloperError', './Cartesian3', './ComponentDatatype', - './PrimitiveType' + './PrimitiveType', + './BoundingSphere', + './Geometry', + './GeometryAttribute', + './GeometryIndices' ], function( defaultValue, DeveloperError, Cartesian3, ComponentDatatype, - PrimitiveType) { + PrimitiveType, + BoundingSphere, + Geometry, + GeometryAttribute, + GeometryIndices) { "use strict"; /** * DOC_TBA * - * @exports CubeMapEllipsoidTessellator - * - * @see BoxTessellator - */ - var CubeMapEllipsoidTessellator = {}; - - /** - * DOC_TBA - * - * @param {Ellipsoid} ellipsoid DOC_TBA. - * @param {Number} numberOfPartitions DOC_TBA. - * @param {String} attributeName DOC_TBA. + * @alias EllipsoidGeometry + * @constructor * * @exception {DeveloperError} numberOfPartitions must be greater than zero. */ - CubeMapEllipsoidTessellator.compute = function(ellipsoid, numberOfPartitions, attributeName) { + var EllipsoidGeometry = function(ellipsoid, numberOfPartitions, attributeName) { if (numberOfPartitions <= 0) { throw new DeveloperError('numberOfPartitions must be greater than zero.'); } - attributeName = defaultValue(attributeName, 'position'); - var positions = []; var indices = []; @@ -178,23 +174,34 @@ define([ flattenedPositions[q++] = item.z; } - var mesh = {}; - mesh.attributes = {}; - mesh.indexLists = []; - - mesh.attributes[attributeName] = { - componentDatatype : ComponentDatatype.FLOAT, - componentsPerAttribute : 3, - values : flattenedPositions + /** + * DOC_TBA + */ + this.attributes = { + position : new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : flattenedPositions + }) }; - mesh.indexLists.push({ - primitiveType : PrimitiveType.TRIANGLES, - values : indices - }); - - return mesh; + /** + * DOC_TBA + */ + this.indexLists = [ + new GeometryIndices({ + primitiveType : PrimitiveType.TRIANGLES, + values : indices + }) + ]; + + /** + * DOC_TBA + */ + this.boundingSphere = BoundingSphere.fromEllipsoid(ellipsoid); }; - return CubeMapEllipsoidTessellator; + EllipsoidGeometry.prototype = new Geometry(); + + return EllipsoidGeometry; }); \ No newline at end of file diff --git a/Source/Core/ExtentTessellator.js b/Source/Core/ExtentTessellator.js index cb2983c3d911..be65e22e81d5 100644 --- a/Source/Core/ExtentTessellator.js +++ b/Source/Core/ExtentTessellator.js @@ -27,7 +27,7 @@ define([ * @exports ExtentTessellator * * @see HeightmapTessellator - * @see CubeMapEllipsoidTessellator + * @see EllipsoidGeometry * @see BoxTessellator * @see PlaneTessellator */ diff --git a/Source/Core/Geometry.js b/Source/Core/Geometry.js index 5d94119918a3..76a526ca3f2b 100644 --- a/Source/Core/Geometry.js +++ b/Source/Core/Geometry.js @@ -1,5 +1,8 @@ /*global define*/ -define(function() { +define([ + './defaultValue' + ], function( + defaultValue) { "use strict"; /** @@ -9,6 +12,8 @@ define(function() { * @constructor */ var Geometry = function(options) { + options = defaultValue(options, defaultValue.EMPTY_OBJECT); + /** * DOC_TBA */ diff --git a/Source/Core/HeightmapTessellator.js b/Source/Core/HeightmapTessellator.js index 916377b9f3ae..922e82c3e8d4 100644 --- a/Source/Core/HeightmapTessellator.js +++ b/Source/Core/HeightmapTessellator.js @@ -29,7 +29,7 @@ define([ * @exports HeightmapTessellator * * @see ExtentTessellator - * @see CubeMapEllipsoidTessellator + * @see EllipsoidGeometry * @see BoxTessellator * @see PlaneTessellator */ diff --git a/Source/Core/MeshFilters.js b/Source/Core/MeshFilters.js index 851cbee98d25..f280d429dc0d 100644 --- a/Source/Core/MeshFilters.js +++ b/Source/Core/MeshFilters.js @@ -201,7 +201,7 @@ define([ * @see MeshFilters.reorderForPostVertexCache * * @example - * var mesh = CubeMapEllipsoidTessellator.compute(...); + * var mesh = new EllipsoidGeometry(...); * mesh = MeshFilters.reorderForPreVertexCache(mesh); */ MeshFilters.reorderForPreVertexCache = function(mesh) { @@ -294,7 +294,7 @@ define([ * by Sander, Nehab, and Barczak * * @example - * var mesh = CubeMapEllipsoidTessellator.compute(...); + * var mesh = new EllipsoidGeometry(...); * mesh = MeshFilters.reorderForPostVertexCache(mesh); */ MeshFilters.reorderForPostVertexCache = function(mesh, cacheCapacity) { diff --git a/Source/Core/PlaneTessellator.js b/Source/Core/PlaneTessellator.js index 4e1544134ec6..83f05973cff4 100644 --- a/Source/Core/PlaneTessellator.js +++ b/Source/Core/PlaneTessellator.js @@ -16,7 +16,7 @@ define([ * * @exports PlaneTessellator * - * @see CubeMapEllipsoidTessellator + * @see EllipsoidGeometry * @see BoxTessellator */ var PlaneTessellator = { diff --git a/Source/Scene/CentralBody.js b/Source/Scene/CentralBody.js index fc28ed8c3af6..83b13f00fca3 100644 --- a/Source/Scene/CentralBody.js +++ b/Source/Scene/CentralBody.js @@ -12,7 +12,6 @@ define([ '../Core/Cartesian4', '../Core/Cartographic', '../Core/ComponentDatatype', - '../Core/CubeMapEllipsoidTessellator', '../Core/Ellipsoid', '../Core/Extent', '../Core/GeographicProjection', @@ -60,7 +59,6 @@ define([ Cartesian4, Cartographic, ComponentDatatype, - CubeMapEllipsoidTessellator, Ellipsoid, Extent, GeographicProjection, diff --git a/Source/Scene/CentralBodySurface.js b/Source/Scene/CentralBodySurface.js index da956db4cf00..9a51d6db0813 100644 --- a/Source/Scene/CentralBodySurface.js +++ b/Source/Scene/CentralBodySurface.js @@ -7,7 +7,7 @@ define([ '../Core/Cartesian2', '../Core/Cartesian3', '../Core/Cartesian4', - '../Core/CubeMapEllipsoidTessellator', + '../Core/EllipsoidGeometry', '../Core/DeveloperError', '../Core/Ellipsoid', '../Core/EllipsoidalOccluder', @@ -42,7 +42,7 @@ define([ Cartesian2, Cartesian3, Cartesian4, - CubeMapEllipsoidTessellator, + EllipsoidGeometry, DeveloperError, Ellipsoid, EllipsoidalOccluder, @@ -722,7 +722,7 @@ define([ if (typeof surface._debug !== 'undefined' && typeof surface._debug.boundingSphereTile !== 'undefined') { if (!surface._debug.boundingSphereVA) { var radius = surface._debug.boundingSphereTile.boundingSphere3D.radius; - var sphere = CubeMapEllipsoidTessellator.compute(new Ellipsoid(radius, radius, radius), 10); + var sphere = new EllipsoidGeometry(new Ellipsoid(radius, radius, radius), 10); MeshFilters.toWireframeInPlace(sphere); surface._debug.boundingSphereVA = context.createVertexArrayFromMesh({ mesh : sphere, diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index e0d6560837a5..e57442cda526 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -86,8 +86,8 @@ define([ command.renderState = this._rs; command.shaderProgram = this._sp; command.uniformMap = appearance.material._uniforms; -// TODO: make this part of mesh - command.boundingVolume = BoundingSphere.fromVertices(this.mesh.attributes.position.values); + command.boundingVolume = this.mesh.boundingSphere; +// command.boundingVolume = BoundingSphere.fromVertices(this.mesh.attributes.position.values); this._commands.push(command); } diff --git a/Source/Scene/SkyAtmosphere.js b/Source/Scene/SkyAtmosphere.js index 737db7a75369..d48f186b9cb4 100644 --- a/Source/Scene/SkyAtmosphere.js +++ b/Source/Scene/SkyAtmosphere.js @@ -1,7 +1,7 @@ /*global define*/ define([ '../Core/defaultValue', - '../Core/CubeMapEllipsoidTessellator', + '../Core/EllipsoidGeometry', '../Core/destroyObject', '../Core/MeshFilters', '../Core/PrimitiveType', @@ -15,7 +15,7 @@ define([ '../Shaders/SkyAtmosphereFS' ], function( defaultValue, - CubeMapEllipsoidTessellator, + EllipsoidGeometry, destroyObject, MeshFilters, PrimitiveType, @@ -133,7 +133,7 @@ define([ var command = this._command; if (typeof command.vertexArray === 'undefined') { - var mesh = CubeMapEllipsoidTessellator.compute(Ellipsoid.fromCartesian3(this._ellipsoid.getRadii().multiplyByScalar(1.025)), 60); + var mesh = new EllipsoidGeometry(Ellipsoid.fromCartesian3(this._ellipsoid.getRadii().multiplyByScalar(1.025)), 60); command.vertexArray = context.createVertexArrayFromMesh({ mesh : mesh, attributeIndices : MeshFilters.createAttributeIndices(mesh), diff --git a/Specs/Core/EllipsoidGeometrySpec.js b/Specs/Core/EllipsoidGeometrySpec.js index d0a9cf2161c6..c3130c36d954 100644 --- a/Specs/Core/EllipsoidGeometrySpec.js +++ b/Specs/Core/EllipsoidGeometrySpec.js @@ -1,11 +1,11 @@ /*global defineSuite*/ defineSuite([ - 'Core/CubeMapEllipsoidTessellator', + 'Core/EllipsoidGeometry', 'Core/Cartesian3', 'Core/Ellipsoid', 'Core/Math' ], function( - CubeMapEllipsoidTessellator, + EllipsoidGeometry, Cartesian3, Ellipsoid, CesiumMath) { @@ -14,26 +14,27 @@ defineSuite([ it('compute0', function() { expect(function() { - return CubeMapEllipsoidTessellator.compute(Ellipsoid.UNIT_SPHERE, -1); + return new EllipsoidGeometry(Ellipsoid.UNIT_SPHERE, -1); }).toThrow(); }); it('compute1', function() { - var m = CubeMapEllipsoidTessellator.compute(Ellipsoid.UNIT_SPHERE, 1); + var m = new EllipsoidGeometry(Ellipsoid.UNIT_SPHERE, 1); expect(m.attributes.position.values.length).toEqual(3 * 8); expect(m.indexLists[0].values.length).toEqual(12 * 3); + expect(m.boundingSphere.radius).toEqual(1); }); it('compute2', function() { - var m = CubeMapEllipsoidTessellator.compute(Ellipsoid.UNIT_SPHERE, 2); + var m = new EllipsoidGeometry(Ellipsoid.UNIT_SPHERE, 2); expect(m.attributes.position.values.length).toEqual(3 * (8 + 6 + 12)); expect(m.indexLists[0].values.length).toEqual(2 * 3 * 4 * 6); }); it('compute3', function() { - var m = CubeMapEllipsoidTessellator.compute(Ellipsoid.UNIT_SPHERE, 3); + var m = new EllipsoidGeometry(Ellipsoid.UNIT_SPHERE, 3); var position = m.attributes.position.values; for ( var i = 0; i < position.length; i += 3) { diff --git a/Specs/Core/MeshFiltersSpec.js b/Specs/Core/MeshFiltersSpec.js index 269768886e7a..3aa53a2f9ec4 100644 --- a/Specs/Core/MeshFiltersSpec.js +++ b/Specs/Core/MeshFiltersSpec.js @@ -239,7 +239,7 @@ defineSuite([ }); it('can reorder indices for the post vertex cache', function() { - var mesh = CubeMapEllipsoidTessellator.compute(new Ellipsoid(10.0, 10.0, 10.0), 100); + var mesh = new EllipsoidGeometry(new Ellipsoid(10.0, 10.0, 10.0), 100); var indices = mesh.indexLists[0].values; var numIndices = indices.length; var maximumIndex = 0; From 0332fc7050fc4074c2839fd59050f47db5275202 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Thu, 9 May 2013 08:39:10 -0400 Subject: [PATCH 010/306] Renamed MeshFilter file --- Apps/CesiumViewer/CesiumViewer.js | 2 +- CHANGES.md | 3 ++- Source/Core/{MeshFilters.js => GeometryFilters.js} | 0 Source/Scene/CentralBody.js | 2 -- Source/Scene/CentralBodySurface.js | 2 +- Source/Scene/EllipsoidPrimitive.js | 2 -- Source/Scene/Polygon.js | 2 +- Source/Scene/Primitive.js | 2 +- Source/Scene/SkyAtmosphere.js | 2 +- Source/Scene/SkyBox.js | 2 +- Specs/Core/{MeshFiltersSpec.js => GeometryFiltersSpec.js} | 0 Specs/Renderer/VertexArrayFactorySpec.js | 2 +- Specs/Scene/MultifrustumSpec.js | 2 +- 13 files changed, 10 insertions(+), 13 deletions(-) rename Source/Core/{MeshFilters.js => GeometryFilters.js} (100%) rename Specs/Core/{MeshFiltersSpec.js => GeometryFiltersSpec.js} (100%) diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index c1c48d02cb3c..70f1c7962a63 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -8,7 +8,7 @@ define([ 'Core/Math', 'Core/Extent', 'Core/ExtentTessellator', - 'Core/MeshFilters', + 'Core/GeometryFilters', 'Scene/Primitive', 'Scene/Appearance', 'Widgets/Dojo/checkForChromeFrame', diff --git a/CHANGES.md b/CHANGES.md index 93f881131568..08f61e176de2 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -9,10 +9,11 @@ Beta Releases * Breaking changes: * Replaced tessellators and meshes with geometry. In particular: * Replaced `CubeMapEllipsoidTessellator` with `EllipsoidGeometry`. + * Renamed `MeshFilters` to `GeometryFilters`. * Renamed `ComponentDatatype.*.toTypedArray` to `ComponentDatatype.*.createTypedArray`. * Replaced `Uniform.getFrameNumber` and `Uniform.getTime` with `Uniform.getFrameState`, which returns the full frame state. * Improved the performance of drawing polygons created with `configureFromPolygonHierarchy`. -* Added `MeshFilters.combine` to combine meshes for better batching. +* Added `GeometryFilters.combine` to combine meshes for better batching. * Added `BoundingSphere.fromEllipsoid`. * Added `DrawCommand.cull` to avoid redundant visibility checks. * Added `czm_morphTime` automatic GLSL uniform. diff --git a/Source/Core/MeshFilters.js b/Source/Core/GeometryFilters.js similarity index 100% rename from Source/Core/MeshFilters.js rename to Source/Core/GeometryFilters.js diff --git a/Source/Scene/CentralBody.js b/Source/Scene/CentralBody.js index 83b13f00fca3..89d4e8b871fe 100644 --- a/Source/Scene/CentralBody.js +++ b/Source/Scene/CentralBody.js @@ -18,7 +18,6 @@ define([ '../Core/Intersect', '../Core/Math', '../Core/Matrix4', - '../Core/MeshFilters', '../Core/Occluder', '../Core/PrimitiveType', '../Core/Transforms', @@ -65,7 +64,6 @@ define([ Intersect, CesiumMath, Matrix4, - MeshFilters, Occluder, PrimitiveType, Transforms, diff --git a/Source/Scene/CentralBodySurface.js b/Source/Scene/CentralBodySurface.js index 9a51d6db0813..f33636e89c09 100644 --- a/Source/Scene/CentralBodySurface.js +++ b/Source/Scene/CentralBodySurface.js @@ -13,7 +13,7 @@ define([ '../Core/EllipsoidalOccluder', '../Core/Intersect', '../Core/Matrix4', - '../Core/MeshFilters', + '../Core/GeometryFilters', '../Core/PrimitiveType', '../Core/Queue', '../Core/TaskProcessor', diff --git a/Source/Scene/EllipsoidPrimitive.js b/Source/Scene/EllipsoidPrimitive.js index c7f493ea8a03..c372003802d1 100644 --- a/Source/Scene/EllipsoidPrimitive.js +++ b/Source/Scene/EllipsoidPrimitive.js @@ -9,7 +9,6 @@ define([ '../Core/destroyObject', '../Core/Ellipsoid', '../Core/Matrix4', - '../Core/MeshFilters', '../Core/BoundingSphere', '../Core/PrimitiveType', '../Renderer/CullFace', @@ -32,7 +31,6 @@ define([ destroyObject, Ellipsoid, Matrix4, - MeshFilters, BoundingSphere, PrimitiveType, CullFace, diff --git a/Source/Scene/Polygon.js b/Source/Scene/Polygon.js index 3ba27152ba50..6f9969f3c7be 100644 --- a/Source/Scene/Polygon.js +++ b/Source/Scene/Polygon.js @@ -14,7 +14,7 @@ define([ '../Core/Cartesian4', '../Core/Cartographic', '../Core/ComponentDatatype', - '../Core/MeshFilters', + '../Core/GeometryFilters', '../Core/PrimitiveType', '../Core/EllipsoidTangentPlane', '../Core/PolygonPipeline', diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index e57442cda526..c6b2db0cbf99 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -2,7 +2,7 @@ define([ '../Core/destroyObject', '../Core/Matrix4', - '../Core/MeshFilters', + '../Core/GeometryFilters', '../Core/PrimitiveType', '../Core/BoundingSphere', '../Renderer/BufferUsage', diff --git a/Source/Scene/SkyAtmosphere.js b/Source/Scene/SkyAtmosphere.js index d48f186b9cb4..b85fb352be38 100644 --- a/Source/Scene/SkyAtmosphere.js +++ b/Source/Scene/SkyAtmosphere.js @@ -3,7 +3,7 @@ define([ '../Core/defaultValue', '../Core/EllipsoidGeometry', '../Core/destroyObject', - '../Core/MeshFilters', + '../Core/GeometryFilters', '../Core/PrimitiveType', '../Core/Ellipsoid', '../Renderer/BufferUsage', diff --git a/Source/Scene/SkyBox.js b/Source/Scene/SkyBox.js index b8d3073d3e55..0990f0afd9ef 100644 --- a/Source/Scene/SkyBox.js +++ b/Source/Scene/SkyBox.js @@ -5,7 +5,7 @@ define([ '../Core/destroyObject', '../Core/DeveloperError', '../Core/Matrix4', - '../Core/MeshFilters', + '../Core/GeometryFilters', '../Core/PrimitiveType', '../Renderer/loadCubeMap', '../Renderer/BufferUsage', diff --git a/Specs/Core/MeshFiltersSpec.js b/Specs/Core/GeometryFiltersSpec.js similarity index 100% rename from Specs/Core/MeshFiltersSpec.js rename to Specs/Core/GeometryFiltersSpec.js diff --git a/Specs/Renderer/VertexArrayFactorySpec.js b/Specs/Renderer/VertexArrayFactorySpec.js index 2f6bc84a293a..e73147244fe2 100644 --- a/Specs/Renderer/VertexArrayFactorySpec.js +++ b/Specs/Renderer/VertexArrayFactorySpec.js @@ -3,7 +3,7 @@ defineSuite([ 'Specs/createContext', 'Specs/destroyContext', 'Core/ComponentDatatype', - 'Core/MeshFilters', + 'Core/GeometryFilters', 'Core/PrimitiveType', 'Core/IndexDatatype', 'Renderer/BufferUsage', diff --git a/Specs/Scene/MultifrustumSpec.js b/Specs/Scene/MultifrustumSpec.js index c20532acf7cc..bb4a343ab080 100644 --- a/Specs/Scene/MultifrustumSpec.js +++ b/Specs/Scene/MultifrustumSpec.js @@ -11,7 +11,7 @@ defineSuite([ 'Core/defaultValue', 'Core/Math', 'Core/Matrix4', - 'Core/MeshFilters', + 'Core/GeometryFilters', 'Core/PrimitiveType', 'Renderer/BlendingState', 'Renderer/BufferUsage', From 039bf6a54c87e405c2cfb6ebe3d1e8541811f755 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Thu, 9 May 2013 08:44:31 -0400 Subject: [PATCH 011/306] Renamed MeshFilter to GeometryFilter --- Apps/CesiumViewer/CesiumViewer.js | 4 +- Apps/Sandcastle/gallery/Custom Rendering.html | 6 +- CHANGES.md | 1 + Source/Core/ExtentTessellator.js | 8 +-- Source/Core/GeometryFilters.js | 52 +++++++------- Source/Renderer/Context.js | 6 +- Source/Scene/CentralBodySurface.js | 6 +- Source/Scene/Polygon.js | 18 ++--- Source/Scene/Primitive.js | 4 +- Source/Scene/SkyAtmosphere.js | 4 +- Source/Scene/SkyBox.js | 4 +- Specs/Core/GeometryFiltersSpec.js | 68 +++++++++---------- Specs/Renderer/VertexArrayFactorySpec.js | 20 +++--- Specs/Scene/MultifrustumSpec.js | 4 +- 14 files changed, 103 insertions(+), 102 deletions(-) diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index 70f1c7962a63..a3103e401e93 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -22,7 +22,7 @@ define([ CesiumMath, Extent, ExtentTessellator, - MeshFilters, + GeometryFilters, Primitive, Appearance, checkForChromeFrame, @@ -63,7 +63,7 @@ define([ CesiumMath.toRadians(30.0)) }); - var primitive = new Primitive(MeshFilters.combine([mesh, anotherMesh]), Appearance.EXAMPLE_APPEARANCE); + var primitive = new Primitive(GeometryFilters.combine([mesh, anotherMesh]), Appearance.EXAMPLE_APPEARANCE); widget.scene.getPrimitives().add(primitive); domClass.remove(win.body(), 'loading'); diff --git a/Apps/Sandcastle/gallery/Custom Rendering.html b/Apps/Sandcastle/gallery/Custom Rendering.html index 35f5bba3e955..7191c0463765 100644 --- a/Apps/Sandcastle/gallery/Custom Rendering.html +++ b/Apps/Sandcastle/gallery/Custom Rendering.html @@ -96,11 +96,11 @@ var minimumCorner = maximumCorner.negate(); Cesium.BoundingSphere.fromPoints([minimumCorner, maximumCorner], colorCommand.boundingVolume); - var mesh = Cesium.MeshFilters.toWireframeInPlace(Cesium.BoxTessellator.compute({ + var mesh = Cesium.GeometryFilters.toWireframe(Cesium.BoxTessellator.compute({ minimumCorner : minimumCorner, maximumCorner : maximumCorner })); - var attributeIndices = Cesium.MeshFilters.createAttributeIndices(mesh); + var attributeIndices = Cesium.GeometryFilters.createAttributeIndices(mesh); colorCommand.vertexArray = pickCommand.vertexArray = context.createVertexArrayFromMesh({ mesh : mesh, @@ -204,7 +204,7 @@ var maximumCorner = dimensions.multiplyByScalar(0.5); var minimumCorner = maximumCorner.negate(); - var mesh = Cesium.MeshFilters.toWireframeInPlace(Cesium.BoxTessellator.compute({ + var mesh = Cesium.GeometryFilters.toWireframe(Cesium.BoxTessellator.compute({ minimumCorner : minimumCorner, maximumCorner : maximumCorner })); diff --git a/CHANGES.md b/CHANGES.md index 08f61e176de2..1e675de5c20f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -10,6 +10,7 @@ Beta Releases * Replaced tessellators and meshes with geometry. In particular: * Replaced `CubeMapEllipsoidTessellator` with `EllipsoidGeometry`. * Renamed `MeshFilters` to `GeometryFilters`. + * Renamed `MeshFilters.toWireframeInPlace` to `GeometryFilters.toWireframe`. * Renamed `ComponentDatatype.*.toTypedArray` to `ComponentDatatype.*.createTypedArray`. * Replaced `Uniform.getFrameNumber` and `Uniform.getTime` with `Uniform.getFrameState`, which returns the full frame state. * Improved the performance of drawing polygons created with `configureFromPolygonHierarchy`. diff --git a/Source/Core/ExtentTessellator.js b/Source/Core/ExtentTessellator.js index be65e22e81d5..3cfc152756ac 100644 --- a/Source/Core/ExtentTessellator.js +++ b/Source/Core/ExtentTessellator.js @@ -178,8 +178,8 @@ define([ * from the extent for creating a vertex array. * * @see Context#createVertexArrayFromMesh - * @see MeshFilters.createAttributeIndices - * @see MeshFilters.toWireframeInPlace + * @see GeometryFilters.createAttributeIndices + * @see GeometryFilters.toWireframe * @see Extent * * @example @@ -195,10 +195,10 @@ define([ * granularity : 0.01, * surfaceHeight : 10000.0 * }); - * mesh = MeshFilters.toWireframeInPlace(mesh); + * mesh = GeometryFilters.toWireframe(mesh); * var va = context.createVertexArrayFromMesh({ * mesh : mesh, - * attributeIndices : MeshFilters.createAttributeIndices(mesh) + * attributeIndices : GeometryFilters.createAttributeIndices(mesh) * }); */ ExtentTessellator.compute = function(description) { diff --git a/Source/Core/GeometryFilters.js b/Source/Core/GeometryFilters.js index f280d429dc0d..462285d51c18 100644 --- a/Source/Core/GeometryFilters.js +++ b/Source/Core/GeometryFilters.js @@ -28,11 +28,11 @@ define([ /** * DOC_TBA * - * @exports MeshFilters + * @exports GeometryFilters * * @see Context#createVertexArrayFromMesh */ - var MeshFilters = {}; + var GeometryFilters = {}; /** * Converts a mesh's triangle indices to line indices. Each list of indices in the mesh's indexList with @@ -51,9 +51,9 @@ define([ * * @example * var mesh = BoxTessellator.compute(); - * mesh = MeshFilters.toWireframeInPlace(mesh); + * mesh = GeometryFilters.toWireframe(mesh); */ - MeshFilters.toWireframeInPlace = function(mesh) { + GeometryFilters.toWireframe = function(mesh) { function addTriangle(lines, i0, i1, i2) { lines.push(i0); lines.push(i1); @@ -135,7 +135,7 @@ define([ /** * DOC_TBA */ - MeshFilters.createAttributeIndices = function(mesh) { + GeometryFilters.createAttributeIndices = function(mesh) { var indices = {}; if (typeof mesh !== 'undefined') { @@ -155,7 +155,7 @@ define([ /** * DOC_TBA */ - MeshFilters.mapAttributeIndices = function(indices, map) { + GeometryFilters.mapAttributeIndices = function(indices, map) { var mappedIndices = {}; if (typeof indices !== 'undefined' && typeof map !== 'undefined') { @@ -169,7 +169,7 @@ define([ return mappedIndices; }; - MeshFilters._computeNumberOfAttributes = function(mesh) { + GeometryFilters._computeNumberOfAttributes = function(mesh) { var numberOfVertices = -1; for ( var property in mesh.attributes) { if (mesh.attributes.hasOwnProperty(property) && mesh.attributes[property].values) { @@ -198,15 +198,15 @@ define([ * * @returns The modified mesh argument, with its vertices and indices reordered for the GPU's pre-vertex-shader cache. * - * @see MeshFilters.reorderForPostVertexCache + * @see GeometryFilters.reorderForPostVertexCache * * @example * var mesh = new EllipsoidGeometry(...); - * mesh = MeshFilters.reorderForPreVertexCache(mesh); + * mesh = GeometryFilters.reorderForPreVertexCache(mesh); */ - MeshFilters.reorderForPreVertexCache = function(mesh) { + GeometryFilters.reorderForPreVertexCache = function(mesh) { if (typeof mesh !== 'undefined') { - var numVertices = MeshFilters._computeNumberOfAttributes(mesh); + var numVertices = GeometryFilters._computeNumberOfAttributes(mesh); var indexCrossReferenceOldToNew = []; for ( var i = 0; i < numVertices; i++) { @@ -287,7 +287,7 @@ define([ * * @returns The modified mesh argument, with its indices optimally reordered for the post-vertex-shader cache. * - * @see MeshFilters.reorderForPreVertexCache + * @see GeometryFilters.reorderForPreVertexCache * @see Tipsify * @see * Fast Triangle Reordering for Vertex Locality and Reduced Overdraw @@ -295,9 +295,9 @@ define([ * * @example * var mesh = new EllipsoidGeometry(...); - * mesh = MeshFilters.reorderForPostVertexCache(mesh); + * mesh = GeometryFilters.reorderForPostVertexCache(mesh); */ - MeshFilters.reorderForPostVertexCache = function(mesh, cacheCapacity) { + GeometryFilters.reorderForPostVertexCache = function(mesh, cacheCapacity) { if (typeof mesh !== 'undefined') { var indexLists = mesh.indexLists; if (typeof indexLists !== 'undefined') { @@ -322,7 +322,7 @@ define([ return mesh; }; - MeshFilters._verifyTrianglesPrimitiveType = function(indexLists) { + GeometryFilters._verifyTrianglesPrimitiveType = function(indexLists) { var length = indexLists.length; for ( var i = 0; i < length; ++i) { if (indexLists[i].primitiveType !== PrimitiveType.TRIANGLES) { @@ -331,7 +331,7 @@ define([ } }; - MeshFilters._copyAttributesDescriptions = function(attributes) { + GeometryFilters._copyAttributesDescriptions = function(attributes) { var newAttributes = {}; for ( var attribute in attributes) { @@ -366,7 +366,7 @@ define([ * @exception {DeveloperError} The mesh's index-lists must have PrimitiveType equal to PrimitiveType.TRIANGLES. * @exception {DeveloperError} All mesh attribute lists must have the same number of attributes. */ - MeshFilters.fitToUnsignedShortIndices = function(mesh) { + GeometryFilters.fitToUnsignedShortIndices = function(mesh) { function createMesh(attributes, primitiveType, indices) { return new Geometry({ attributes : attributes, @@ -380,9 +380,9 @@ define([ var meshes = []; if (typeof mesh !== 'undefined') { - MeshFilters._verifyTrianglesPrimitiveType(mesh.indexLists); + GeometryFilters._verifyTrianglesPrimitiveType(mesh.indexLists); - var numberOfVertices = MeshFilters._computeNumberOfAttributes(mesh); + var numberOfVertices = GeometryFilters._computeNumberOfAttributes(mesh); // If there's an index list and more than 64K attributes, it is possible that // some indices are outside the range of unsigned short [0, 64K - 1] @@ -397,7 +397,7 @@ define([ var oldToNewIndex = []; var newIndices = []; var currentIndex = 0; - var newAttributes = MeshFilters._copyAttributesDescriptions(mesh.attributes); + var newAttributes = GeometryFilters._copyAttributesDescriptions(mesh.attributes); var originalIndices = indexLists[i].values; var numberOfIndices = originalIndices.length; @@ -444,7 +444,7 @@ define([ oldToNewIndex = []; newIndices = []; currentIndex = 0; - newAttributes = MeshFilters._copyAttributesDescriptions(mesh.attributes); + newAttributes = GeometryFilters._copyAttributesDescriptions(mesh.attributes); } } @@ -464,7 +464,7 @@ define([ /** * DOC_TBA */ - MeshFilters.projectTo2D = function(mesh, projection) { + GeometryFilters.projectTo2D = function(mesh, projection) { if (typeof mesh !== 'undefined' && typeof mesh.attributes !== 'undefined' && typeof mesh.attributes.position !== 'undefined') { projection = typeof projection !== 'undefined' ? projection : new GeographicProjection(); var ellipsoid = projection.getEllipsoid(); @@ -519,11 +519,11 @@ define([ * @exception {DeveloperError} The attribute componentDatatype must be ComponentDatatype.FLOAT. * * @example - * mesh = MeshFilters.encodeAttribute(mesh, 'position3D', 'position3DHigh', 'position3DLow'); + * mesh = GeometryFilters.encodeAttribute(mesh, 'position3D', 'position3DHigh', 'position3DLow'); * * @see EncodedCartesian3 */ - MeshFilters.encodeAttribute = function(mesh, attributeName, attributeHighName, attributeLowName) { + GeometryFilters.encodeAttribute = function(mesh, attributeName, attributeHighName, attributeLowName) { attributeName = defaultValue(attributeName, 'position'); attributeHighName = defaultValue(attributeHighName, 'positionHigh'); attributeLowName = defaultValue(attributeLowName, 'positionLow'); @@ -621,7 +621,7 @@ define([ * * @exception {DeveloperError} meshes is required and must have length greater than zero. */ - MeshFilters.combine = function(meshes) { + GeometryFilters.combine = function(meshes) { if ((typeof meshes === 'undefined') || (meshes.length < 1)) { throw new DeveloperError('meshes is required.'); } @@ -744,5 +744,5 @@ define([ }); }; - return MeshFilters; + return GeometryFilters; }); diff --git a/Source/Renderer/Context.js b/Source/Renderer/Context.js index 676852d394b9..0468a4d9be2a 100644 --- a/Source/Renderer/Context.js +++ b/Source/Renderer/Context.js @@ -2349,7 +2349,7 @@ define([ * @see Context#createVertexArray * @see Context#createVertexBuffer * @see Context#createIndexBuffer - * @see MeshFilters.createAttributeIndices + * @see GeometryFilters.createAttributeIndices * @see ShaderProgram * @see BoxTessellator * @@ -2360,7 +2360,7 @@ define([ * var mesh = BoxTessellator.compute(); * var va = context.createVertexArrayFromMesh({ * mesh : mesh, - * attributeIndices : MeshFilters.createAttributeIndices(mesh), + * attributeIndices : GeometryFilters.createAttributeIndices(mesh), * }); * * //////////////////////////////////////////////////////////////////////////////// @@ -2369,7 +2369,7 @@ define([ * // single vertex buffer. The vertex and index buffer have static draw usage. * var va = context.createVertexArrayFromMesh({ * mesh : mesh, - * attributeIndices : MeshFilters.createAttributeIndices(mesh), + * attributeIndices : GeometryFilters.createAttributeIndices(mesh), * bufferUsage : BufferUsage.STATIC_DRAW, * vertexLayout : VertexLayout.INTERLEAVED * }); diff --git a/Source/Scene/CentralBodySurface.js b/Source/Scene/CentralBodySurface.js index f33636e89c09..5dbdd70b5a51 100644 --- a/Source/Scene/CentralBodySurface.js +++ b/Source/Scene/CentralBodySurface.js @@ -48,7 +48,7 @@ define([ EllipsoidalOccluder, Intersect, Matrix4, - MeshFilters, + GeometryFilters, PrimitiveType, Queue, TaskProcessor, @@ -723,10 +723,10 @@ define([ if (!surface._debug.boundingSphereVA) { var radius = surface._debug.boundingSphereTile.boundingSphere3D.radius; var sphere = new EllipsoidGeometry(new Ellipsoid(radius, radius, radius), 10); - MeshFilters.toWireframeInPlace(sphere); + GeometryFilters.toWireframe(sphere); surface._debug.boundingSphereVA = context.createVertexArrayFromMesh({ mesh : sphere, - attributeIndices : MeshFilters.createAttributeIndices(sphere) + attributeIndices : GeometryFilters.createAttributeIndices(sphere) }); } diff --git a/Source/Scene/Polygon.js b/Source/Scene/Polygon.js index 6f9969f3c7be..71b3f5dd8635 100644 --- a/Source/Scene/Polygon.js +++ b/Source/Scene/Polygon.js @@ -50,7 +50,7 @@ define([ Cartesian4, Cartographic, ComponentDatatype, - MeshFilters, + GeometryFilters, PrimitiveType, EllipsoidTangentPlane, PolygonPipeline, @@ -596,10 +596,10 @@ define([ return undefined; } - mesh = MeshFilters.combine(meshes); + mesh = GeometryFilters.combine(meshes); mesh = PolygonPipeline.scaleToGeodeticHeight(mesh, polygon.height, polygon.ellipsoid); - mesh = MeshFilters.reorderForPostVertexCache(mesh); - mesh = MeshFilters.reorderForPreVertexCache(mesh); + mesh = GeometryFilters.reorderForPostVertexCache(mesh); + mesh = GeometryFilters.reorderForPreVertexCache(mesh); if (polygon._mode === SceneMode.SCENE3D) { mesh.attributes.position2DHigh = { // Not actually used in shader @@ -608,9 +608,9 @@ define([ mesh.attributes.position2DLow = { // Not actually used in shader value : [0.0, 0.0] }; - mesh = MeshFilters.encodeAttribute(mesh, 'position', 'position3DHigh', 'position3DLow'); + mesh = GeometryFilters.encodeAttribute(mesh, 'position', 'position3DHigh', 'position3DLow'); } else { - mesh = MeshFilters.projectTo2D(mesh, polygon._projection); + mesh = GeometryFilters.projectTo2D(mesh, polygon._projection); if (polygon._mode !== SceneMode.SCENE3D) { var projectedPositions = mesh.attributes.position2D.values; @@ -625,11 +625,11 @@ define([ polygon._boundingVolume2D.center = new Cartesian3(0.0, center2DPositions.x, center2DPositions.y); } - mesh = MeshFilters.encodeAttribute(mesh, 'position3D', 'position3DHigh', 'position3DLow'); - mesh = MeshFilters.encodeAttribute(mesh, 'position2D', 'position2DHigh', 'position2DLow'); + mesh = GeometryFilters.encodeAttribute(mesh, 'position3D', 'position3DHigh', 'position3DLow'); + mesh = GeometryFilters.encodeAttribute(mesh, 'position2D', 'position2DHigh', 'position2DLow'); } - return MeshFilters.fitToUnsignedShortIndices(mesh); + return GeometryFilters.fitToUnsignedShortIndices(mesh); } function getGranularity(polygon, mode) { diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index c6b2db0cbf99..d65c4ca7bb65 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -13,7 +13,7 @@ define([ ], function( destroyObject, Matrix4, - MeshFilters, + GeometryFilters, PrimitiveType, BoundingSphere, BufferUsage, @@ -67,7 +67,7 @@ define([ // TODO: throw if mesh and appearance are not defined if (typeof this._va === 'undefined') { - var attributeIndices = MeshFilters.createAttributeIndices(this.mesh); + var attributeIndices = GeometryFilters.createAttributeIndices(this.mesh); var appearance = this.appearance; this._va = context.createVertexArrayFromMesh({ diff --git a/Source/Scene/SkyAtmosphere.js b/Source/Scene/SkyAtmosphere.js index b85fb352be38..7a6d5dca448f 100644 --- a/Source/Scene/SkyAtmosphere.js +++ b/Source/Scene/SkyAtmosphere.js @@ -17,7 +17,7 @@ define([ defaultValue, EllipsoidGeometry, destroyObject, - MeshFilters, + GeometryFilters, PrimitiveType, Ellipsoid, BufferUsage, @@ -136,7 +136,7 @@ define([ var mesh = new EllipsoidGeometry(Ellipsoid.fromCartesian3(this._ellipsoid.getRadii().multiplyByScalar(1.025)), 60); command.vertexArray = context.createVertexArrayFromMesh({ mesh : mesh, - attributeIndices : MeshFilters.createAttributeIndices(mesh), + attributeIndices : GeometryFilters.createAttributeIndices(mesh), bufferUsage : BufferUsage.STATIC_DRAW }); command.primitiveType = PrimitiveType.TRIANGLES; diff --git a/Source/Scene/SkyBox.js b/Source/Scene/SkyBox.js index 0990f0afd9ef..5c73a3a04a72 100644 --- a/Source/Scene/SkyBox.js +++ b/Source/Scene/SkyBox.js @@ -20,7 +20,7 @@ define([ destroyObject, DeveloperError, Matrix4, - MeshFilters, + GeometryFilters, PrimitiveType, loadCubeMap, BufferUsage, @@ -151,7 +151,7 @@ define([ var mesh = BoxTessellator.compute({ dimensions : new Cartesian3(2.0, 2.0, 2.0) }); - var attributeIndices = MeshFilters.createAttributeIndices(mesh); + var attributeIndices = GeometryFilters.createAttributeIndices(mesh); command.primitiveType = PrimitiveType.TRIANGLES; command.modelMatrix = Matrix4.IDENTITY.clone(); diff --git a/Specs/Core/GeometryFiltersSpec.js b/Specs/Core/GeometryFiltersSpec.js index 3aa53a2f9ec4..fd632d01a3b4 100644 --- a/Specs/Core/GeometryFiltersSpec.js +++ b/Specs/Core/GeometryFiltersSpec.js @@ -1,6 +1,6 @@ /*global defineSuite*/ defineSuite([ - 'Core/MeshFilters', + 'Core/GeometryFilters', 'Core/PrimitiveType', 'Core/ComponentDatatype', 'Core/EllipsoidGeometry', @@ -13,7 +13,7 @@ defineSuite([ 'Core/GeometryAttribute', 'Core/GeometryIndices' ], function( - MeshFilters, + GeometryFilters, PrimitiveType, ComponentDatatype, EllipsoidGeometry, @@ -29,7 +29,7 @@ defineSuite([ /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/ it('converts triangles to wireframe in place', function() { - var mesh = MeshFilters.toWireframeInPlace({ + var mesh = GeometryFilters.toWireframe({ indexLists : [{ primitiveType : PrimitiveType.TRIANGLES, values : [0, 1, 2, 3, 4, 5] @@ -57,7 +57,7 @@ defineSuite([ }); it('converts a triangle fan to wireframe in place', function() { - var mesh = MeshFilters.toWireframeInPlace({ + var mesh = GeometryFilters.toWireframe({ indexLists : [{ primitiveType : PrimitiveType.TRIANGLE_FAN, values : [0, 1, 2, 3] @@ -85,7 +85,7 @@ defineSuite([ }); it('converts a triangle strip to wireframe in place', function() { - var mesh = MeshFilters.toWireframeInPlace({ + var mesh = GeometryFilters.toWireframe({ indexLists : [{ primitiveType : PrimitiveType.TRIANGLE_STRIP, values : [0, 1, 2, 3] @@ -121,7 +121,7 @@ defineSuite([ } }; - var indices = MeshFilters.createAttributeIndices(mesh); + var indices = GeometryFilters.createAttributeIndices(mesh); var validIndices = [0, 1, 2]; expect(validIndices).toContain(indices.position); @@ -138,7 +138,7 @@ defineSuite([ colors : 2 }; - var mappedIndices = MeshFilters.mapAttributeIndices(indices, { + var mappedIndices = GeometryFilters.mapAttributeIndices(indices, { positions : 'position', normals : 'normal', colors : 'color' @@ -165,7 +165,7 @@ defineSuite([ componentsPerAttribute : 3, values : [0, 1, 2, 3, 4, 5] }; - mesh = MeshFilters.reorderForPreVertexCache(mesh); + mesh = GeometryFilters.reorderForPreVertexCache(mesh); }).toThrow(); }); @@ -195,7 +195,7 @@ defineSuite([ componentsPerAttribute : 3, values : [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17] }; - MeshFilters.reorderForPreVertexCache(mesh); + GeometryFilters.reorderForPreVertexCache(mesh); expect(mesh.indexLists[0].values[0]).toEqual(0); expect(mesh.indexLists[0].values[1]).toEqual(1); @@ -252,7 +252,7 @@ defineSuite([ maximumIndex : maximumIndex, cacheSize : 24}); expect(ACMRbefore).toBeGreaterThan(1.00); - mesh = MeshFilters.reorderForPostVertexCache(mesh); + mesh = GeometryFilters.reorderForPostVertexCache(mesh); indices = mesh.indexLists[0].values; var ACMRafter = Tipsify.calculateACMR({indices : indices, maximumIndex : maximumIndex, @@ -280,7 +280,7 @@ defineSuite([ }] }; - var meshes = MeshFilters.fitToUnsignedShortIndices(mesh); + var meshes = GeometryFilters.fitToUnsignedShortIndices(mesh); expect(meshes.length).toEqual(1); expect(meshes[0]).toBe(mesh); @@ -307,7 +307,7 @@ defineSuite([ }] }; - var meshes = MeshFilters.fitToUnsignedShortIndices(mesh); + var meshes = GeometryFilters.fitToUnsignedShortIndices(mesh); expect(meshes.length).toEqual(1); expect(meshes[0].attributes.time.componentDatatype).toEqual(ComponentDatatype.FLOAT); @@ -346,7 +346,7 @@ defineSuite([ }] }; - var meshes = MeshFilters.fitToUnsignedShortIndices(mesh); + var meshes = GeometryFilters.fitToUnsignedShortIndices(mesh); expect(meshes.length).toEqual(2); @@ -374,7 +374,7 @@ defineSuite([ }; expect(function() { - return MeshFilters.fitToUnsignedShortIndices(mesh); + return GeometryFilters.fitToUnsignedShortIndices(mesh); }).toThrow(); }); @@ -401,7 +401,7 @@ defineSuite([ }; expect(function() { - return MeshFilters.fitToUnsignedShortIndices(mesh); + return GeometryFilters.fitToUnsignedShortIndices(mesh); }).toThrow(); }); @@ -417,7 +417,7 @@ defineSuite([ values : [p1.x, p1.y, p1.z, p2.x, p2.y, p2.z] }; - mesh = MeshFilters.projectTo2D(mesh); + mesh = GeometryFilters.projectTo2D(mesh); var ellipsoid = Ellipsoid.WGS84; var projection = new GeographicProjection(); @@ -437,7 +437,7 @@ defineSuite([ expect(mesh.attributes.position3D.values[5]).toEqual(p2.z); }); - it('MeshFilters.encodeAttribute encodes positions', function() { + it('GeometryFilters.encodeAttribute encodes positions', function() { var c = new Cartesian3(-10000000.0, 0.0, 10000000.0); var encoded = EncodedCartesian3.fromCartesian(c); @@ -450,7 +450,7 @@ defineSuite([ } } }; - mesh = MeshFilters.encodeAttribute(mesh); + mesh = GeometryFilters.encodeAttribute(mesh); expect(mesh.attributes.positionHigh).toBeDefined(); expect(mesh.attributes.positionHigh.values[0]).toEqual(encoded.high.x); @@ -463,29 +463,29 @@ defineSuite([ expect(mesh.attributes.position).not.toBeDefined(); }); - it('MeshFilters.encodeAttribute throws without a mesh', function() { + it('GeometryFilters.encodeAttribute throws without a mesh', function() { expect(function() { - MeshFilters.encodeAttribute(undefined); + GeometryFilters.encodeAttribute(undefined); }).toThrow(); }); - it('MeshFilters.encodeAttribute throws with mesh without attributes property', function() { + it('GeometryFilters.encodeAttribute throws with mesh without attributes property', function() { expect(function() { - MeshFilters.encodeAttribute({}); + GeometryFilters.encodeAttribute({}); }).toThrow(); }); - it('MeshFilters.encodeAttribute throws without attribute', function() { + it('GeometryFilters.encodeAttribute throws without attribute', function() { expect(function() { var mesh = { attributes : { } }; - MeshFilters.encodeAttribute(mesh); + GeometryFilters.encodeAttribute(mesh); }).toThrow(); }); - it('MeshFilters.encodeAttribute throws without ComponentDatatype.FLOAT', function() { + it('GeometryFilters.encodeAttribute throws without ComponentDatatype.FLOAT', function() { expect(function() { var mesh = { attributes : { @@ -494,11 +494,11 @@ defineSuite([ values : [0.0] } }; - MeshFilters.encodeAttribute(mesh); + GeometryFilters.encodeAttribute(mesh); }).toThrow(); }); - it('MeshFilters.combine combines one mesh', function() { + it('GeometryFilters.combine combines one mesh', function() { var mesh = new Geometry({ attributes : new GeometryAttribute({ position : { @@ -509,11 +509,11 @@ defineSuite([ }) }); - var combinedMesh = MeshFilters.combine([mesh]); + var combinedMesh = GeometryFilters.combine([mesh]); expect(combinedMesh).toBe(mesh); }); - it('MeshFilters.combine combines several meshes', function() { + it('GeometryFilters.combine combines several meshes', function() { var mesh = new Geometry({ attributes : { position : new GeometryAttribute({ @@ -564,7 +564,7 @@ defineSuite([ })] }); - var combinedMesh = MeshFilters.combine([mesh, anotherMesh]); + var combinedMesh = GeometryFilters.combine([mesh, anotherMesh]); expect(combinedMesh).toEqual(new Geometry({ attributes : { position : new GeometryAttribute({ @@ -593,15 +593,15 @@ defineSuite([ })); }); - it('MeshFilters.combine throws with meshes', function() { + it('GeometryFilters.combine throws with meshes', function() { expect(function() { - MeshFilters.combine(); + GeometryFilters.combine(); }).toThrow(); }); - it('MeshFilters.combine throws when meshes.length is zero', function() { + it('GeometryFilters.combine throws when meshes.length is zero', function() { expect(function() { - MeshFilters.combine([]); + GeometryFilters.combine([]); }).toThrow(); }); diff --git a/Specs/Renderer/VertexArrayFactorySpec.js b/Specs/Renderer/VertexArrayFactorySpec.js index e73147244fe2..3dd14d9f3186 100644 --- a/Specs/Renderer/VertexArrayFactorySpec.js +++ b/Specs/Renderer/VertexArrayFactorySpec.js @@ -13,7 +13,7 @@ defineSuite([ createContext, destroyContext, ComponentDatatype, - MeshFilters, + GeometryFilters, PrimitiveType, IndexDatatype, BufferUsage, @@ -66,7 +66,7 @@ defineSuite([ var va = context.createVertexArrayFromMesh({ mesh : mesh, - attributeIndices : MeshFilters.createAttributeIndices(mesh) + attributeIndices : GeometryFilters.createAttributeIndices(mesh) }); expect(va.getNumberOfAttributes()).toEqual(1); @@ -95,7 +95,7 @@ defineSuite([ var va = context.createVertexArrayFromMesh({ mesh : mesh, - attributeIndices : MeshFilters.createAttributeIndices(mesh), + attributeIndices : GeometryFilters.createAttributeIndices(mesh), vertexLayout : VertexLayout.INTERLEAVED, bufferUsage : BufferUsage.STATIC_DRAW }); @@ -131,7 +131,7 @@ defineSuite([ var va = context.createVertexArrayFromMesh({ mesh : mesh, - attributeIndices : MeshFilters.createAttributeIndices(mesh) + attributeIndices : GeometryFilters.createAttributeIndices(mesh) }); expect(va.getNumberOfAttributes()).toEqual(2); @@ -172,7 +172,7 @@ defineSuite([ var va = context.createVertexArrayFromMesh({ mesh : mesh, - attributeIndices : MeshFilters.createAttributeIndices(mesh), + attributeIndices : GeometryFilters.createAttributeIndices(mesh), vertexLayout : VertexLayout.INTERLEAVED }); @@ -216,7 +216,7 @@ defineSuite([ var va = context.createVertexArrayFromMesh({ mesh : mesh, - attributeIndices : MeshFilters.createAttributeIndices(mesh), + attributeIndices : GeometryFilters.createAttributeIndices(mesh), vertexLayout : VertexLayout.INTERLEAVED }); @@ -263,7 +263,7 @@ defineSuite([ } }; - var attributeIndices = MeshFilters.createAttributeIndices(mesh); + var attributeIndices = GeometryFilters.createAttributeIndices(mesh); var va = context.createVertexArrayFromMesh({ mesh : mesh, attributeIndices : attributeIndices, @@ -323,7 +323,7 @@ defineSuite([ } }; - var attributeIndices = MeshFilters.createAttributeIndices(mesh); + var attributeIndices = GeometryFilters.createAttributeIndices(mesh); var va = context.createVertexArrayFromMesh({ mesh : mesh, attributeIndices : attributeIndices, @@ -397,7 +397,7 @@ defineSuite([ } }; - var attributeIndices = MeshFilters.createAttributeIndices(mesh); + var attributeIndices = GeometryFilters.createAttributeIndices(mesh); var va = context.createVertexArrayFromMesh({ mesh : mesh, attributeIndices : attributeIndices, @@ -465,7 +465,7 @@ defineSuite([ } }; - var attributeIndices = MeshFilters.createAttributeIndices(mesh); + var attributeIndices = GeometryFilters.createAttributeIndices(mesh); var va = context.createVertexArrayFromMesh({ mesh : mesh, attributeIndices : attributeIndices, diff --git a/Specs/Scene/MultifrustumSpec.js b/Specs/Scene/MultifrustumSpec.js index bb4a343ab080..f4b3c48b246a 100644 --- a/Specs/Scene/MultifrustumSpec.js +++ b/Specs/Scene/MultifrustumSpec.js @@ -33,7 +33,7 @@ defineSuite([ defaultValue, CesiumMath, Matrix4, - MeshFilters, + GeometryFilters, PrimitiveType, BlendingState, BufferUsage, @@ -216,7 +216,7 @@ defineSuite([ minimumCorner: minimumCorner, maximumCorner: maximumCorner }); - var attributeIndices = MeshFilters.createAttributeIndices(mesh); + var attributeIndices = GeometryFilters.createAttributeIndices(mesh); this._va = context.createVertexArrayFromMesh({ mesh: mesh, attributeIndices: attributeIndices, From eee2853bc3e510d03322716b65250b4561000d29 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Thu, 9 May 2013 08:59:53 -0400 Subject: [PATCH 012/306] Renamed BoxGeometry file --- CHANGES.md | 1 + Source/Core/{BoxTessellator.js => BoxGeometry.js} | 0 Source/Scene/EllipsoidPrimitive.js | 2 +- Source/Scene/SkyBox.js | 2 +- Specs/Core/{BoxTessellatorSpec.js => BoxGeometrySpec.js} | 2 +- Specs/Scene/MultifrustumSpec.js | 2 +- 6 files changed, 5 insertions(+), 4 deletions(-) rename Source/Core/{BoxTessellator.js => BoxGeometry.js} (100%) rename Specs/Core/{BoxTessellatorSpec.js => BoxGeometrySpec.js} (96%) diff --git a/CHANGES.md b/CHANGES.md index 1e675de5c20f..f8589d9817d3 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -9,6 +9,7 @@ Beta Releases * Breaking changes: * Replaced tessellators and meshes with geometry. In particular: * Replaced `CubeMapEllipsoidTessellator` with `EllipsoidGeometry`. + * Replaced `BoxTessellator` with `BoxGeometry`. * Renamed `MeshFilters` to `GeometryFilters`. * Renamed `MeshFilters.toWireframeInPlace` to `GeometryFilters.toWireframe`. * Renamed `ComponentDatatype.*.toTypedArray` to `ComponentDatatype.*.createTypedArray`. diff --git a/Source/Core/BoxTessellator.js b/Source/Core/BoxGeometry.js similarity index 100% rename from Source/Core/BoxTessellator.js rename to Source/Core/BoxGeometry.js diff --git a/Source/Scene/EllipsoidPrimitive.js b/Source/Scene/EllipsoidPrimitive.js index c372003802d1..228127859e56 100644 --- a/Source/Scene/EllipsoidPrimitive.js +++ b/Source/Scene/EllipsoidPrimitive.js @@ -1,6 +1,6 @@ /*global define*/ define([ - '../Core/BoxTessellator', + '../Core/BoxGeometry', '../Core/Cartesian3', '../Core/Cartesian4', '../Core/combine', diff --git a/Source/Scene/SkyBox.js b/Source/Scene/SkyBox.js index 5c73a3a04a72..93a6cd2a3419 100644 --- a/Source/Scene/SkyBox.js +++ b/Source/Scene/SkyBox.js @@ -1,6 +1,6 @@ /*global define*/ define([ - '../Core/BoxTessellator', + '../Core/BoxGeometry', '../Core/Cartesian3', '../Core/destroyObject', '../Core/DeveloperError', diff --git a/Specs/Core/BoxTessellatorSpec.js b/Specs/Core/BoxGeometrySpec.js similarity index 96% rename from Specs/Core/BoxTessellatorSpec.js rename to Specs/Core/BoxGeometrySpec.js index 65abd664f2fe..2055632fb519 100644 --- a/Specs/Core/BoxTessellatorSpec.js +++ b/Specs/Core/BoxGeometrySpec.js @@ -1,6 +1,6 @@ /*global defineSuite*/ defineSuite([ - 'Core/BoxTessellator', + 'Core/BoxGeometry', 'Core/Cartesian3' ], function( BoxTessellator, diff --git a/Specs/Scene/MultifrustumSpec.js b/Specs/Scene/MultifrustumSpec.js index f4b3c48b246a..98b6d0c8d006 100644 --- a/Specs/Scene/MultifrustumSpec.js +++ b/Specs/Scene/MultifrustumSpec.js @@ -4,7 +4,7 @@ defineSuite([ 'Specs/destroyScene', 'Core/destroyObject', 'Core/BoundingSphere', - 'Core/BoxTessellator', + 'Core/BoxGeometry', 'Core/Cartesian2', 'Core/Cartesian3', 'Core/Color', From 0a40ed77967f5bc166a92bcefd2ca2b8d5103d7f Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Thu, 9 May 2013 09:50:43 -0400 Subject: [PATCH 013/306] Created BoxGeometry from BoxTessellator --- Apps/Sandcastle/gallery/Custom Rendering.html | 4 +- Source/Core/BoxGeometry.js | 135 ++++++++++-------- Source/Core/ExtentTessellator.js | 5 - Source/Core/GeometryFilters.js | 10 +- Source/Core/HeightmapTessellator.js | 5 - Source/Core/PlaneTessellator.js | 3 - Source/Renderer/Context.js | 5 +- Source/Scene/EllipsoidPrimitive.js | 4 +- Source/Scene/SkyBox.js | 4 +- Source/Shaders/EllipsoidVS.glsl | 2 +- Specs/Core/BoxGeometrySpec.js | 8 +- Specs/Scene/MultifrustumSpec.js | 4 +- 12 files changed, 92 insertions(+), 97 deletions(-) diff --git a/Apps/Sandcastle/gallery/Custom Rendering.html b/Apps/Sandcastle/gallery/Custom Rendering.html index 7191c0463765..cb54420aa338 100644 --- a/Apps/Sandcastle/gallery/Custom Rendering.html +++ b/Apps/Sandcastle/gallery/Custom Rendering.html @@ -96,7 +96,7 @@ var minimumCorner = maximumCorner.negate(); Cesium.BoundingSphere.fromPoints([minimumCorner, maximumCorner], colorCommand.boundingVolume); - var mesh = Cesium.GeometryFilters.toWireframe(Cesium.BoxTessellator.compute({ + var mesh = Cesium.GeometryFilters.toWireframe(new Cesium.BoxGeometry({ minimumCorner : minimumCorner, maximumCorner : maximumCorner })); @@ -204,7 +204,7 @@ var maximumCorner = dimensions.multiplyByScalar(0.5); var minimumCorner = maximumCorner.negate(); - var mesh = Cesium.GeometryFilters.toWireframe(Cesium.BoxTessellator.compute({ + var mesh = Cesium.GeometryFilters.toWireframe(new Cesium.BoxGeometry({ minimumCorner : minimumCorner, maximumCorner : maximumCorner })); diff --git a/Source/Core/BoxGeometry.js b/Source/Core/BoxGeometry.js index 3a9bfb7c13a5..36cff4e4151c 100644 --- a/Source/Core/BoxGeometry.js +++ b/Source/Core/BoxGeometry.js @@ -4,93 +4,104 @@ define([ './Cartesian3', './ComponentDatatype', './PrimitiveType', - './defaultValue' + './defaultValue', + './BoundingSphere', + './Geometry', + './GeometryAttribute', + './GeometryIndices' ], function( DeveloperError, Cartesian3, ComponentDatatype, PrimitiveType, - defaultValue) { + defaultValue, + BoundingSphere, + Geometry, + GeometryAttribute, + GeometryIndices) { "use strict"; /** * DOC_TBA * - * @alias BoxTessellator - * @exports BoxTessellator + * @alias EllipsoidGeometry + * @constructor * - * @see EllipsoidGeometry - * @see PlaneTessellator + * @exception {DeveloperError} All dimensions components must be greater than or equal to zero. */ - var BoxTessellator = { - /** - * DOC_TBA - * - * @exception {DeveloperError} All dimensions' components must be greater than or equal to zero. - */ - compute : function(options) { - options = defaultValue(options, defaultValue.EMPTY_OBJECT); - - var minimumCorner; - var maximumCorner; + var BoxGeometry = function(options) { + options = defaultValue(options, defaultValue.EMPTY_OBJECT); - if (typeof options.minimumCorner !== 'undefined' && typeof options.maximumCorner !== 'undefined') { - minimumCorner = options.minimumCorner; - maximumCorner = options.maximumCorner; - } else { - var dimensions = typeof options.dimensions !== 'undefined' ? options.dimensions : new Cartesian3(1.0, 1.0, 1.0); + var minimumCorner; + var maximumCorner; - if (dimensions.x < 0 || dimensions.y < 0 || dimensions.z < 0) { - throw new DeveloperError('All dimensions components must be greater than or equal to zero.'); - } + if (typeof options.minimumCorner !== 'undefined' && typeof options.maximumCorner !== 'undefined') { + minimumCorner = options.minimumCorner; + maximumCorner = options.maximumCorner; + } else { + var dimensions = typeof options.dimensions !== 'undefined' ? options.dimensions : new Cartesian3(1.0, 1.0, 1.0); - var corner = dimensions.multiplyByScalar(0.5); - minimumCorner = corner.negate(); - maximumCorner = corner; + if (dimensions.x < 0 || dimensions.y < 0 || dimensions.z < 0) { + throw new DeveloperError('All dimensions components must be greater than or equal to zero.'); } - var mesh = {}; - mesh.attributes = {}; - mesh.indexLists = []; + var corner = dimensions.multiplyByScalar(0.5); + minimumCorner = corner.negate(); + maximumCorner = corner; + } - // 8 corner points. - mesh.attributes.position = { + /** + * DOC_TBA + */ + this.attributes = { + position : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 3, values : [ - minimumCorner.x, minimumCorner.y, minimumCorner.z, - maximumCorner.x, minimumCorner.y, minimumCorner.z, - maximumCorner.x, maximumCorner.y, minimumCorner.z, - minimumCorner.x, maximumCorner.y, minimumCorner.z, - minimumCorner.x, minimumCorner.y, maximumCorner.z, - maximumCorner.x, minimumCorner.y, maximumCorner.z, - maximumCorner.x, maximumCorner.y, maximumCorner.z, - minimumCorner.x, maximumCorner.y, maximumCorner.z - ] - }; + // 8 corner points. + minimumCorner.x, minimumCorner.y, minimumCorner.z, + maximumCorner.x, minimumCorner.y, minimumCorner.z, + maximumCorner.x, maximumCorner.y, minimumCorner.z, + minimumCorner.x, maximumCorner.y, minimumCorner.z, + minimumCorner.x, minimumCorner.y, maximumCorner.z, + maximumCorner.x, minimumCorner.y, maximumCorner.z, + maximumCorner.x, maximumCorner.y, maximumCorner.z, + minimumCorner.x, maximumCorner.y, maximumCorner.z + ] + }) + }; - // 12 triangles: 6 faces, 2 triangles each. - mesh.indexLists.push({ + /** + * DOC_TBA + */ + this.indexLists = [ + new GeometryIndices({ + // 12 triangles: 6 faces, 2 triangles each. primitiveType : PrimitiveType.TRIANGLES, values : [ - 4, 5, 6, // Top: plane z = corner.Z - 4, 6, 7, - 1, 0, 3, // Bottom: plane z = -corner.Z - 1, 3, 2, - 1, 6, 5, // Side: plane x = corner.X - 1, 2, 6, - 2, 3, 7, // Side: plane y = corner.Y - 2, 7, 6, - 3, 0, 4, // Side: plane x = -corner.X - 3, 4, 7, - 0, 1, 5, // Side: plane y = -corner.Y - 0, 5, 4 - ] - }); + 4, 5, 6, // Top: plane z = corner.Z + 4, 6, 7, + 1, 0, 3, // Bottom: plane z = -corner.Z + 1, 3, 2, + 1, 6, 5, // Side: plane x = corner.X + 1, 2, 6, + 2, 3, 7, // Side: plane y = corner.Y + 2, 7, 6, + 3, 0, 4, // Side: plane x = -corner.X + 3, 4, 7, + 0, 1, 5, // Side: plane y = -corner.Y + 0, 5, 4 + ] + }) + ]; - return mesh; - } + /** + * DOC_TBA + */ + this.boundingSphere = new BoundingSphere(new Cartesian3(), maximumCorner.subtract(minimumCorner).magnitude() * 0.5); }; - return BoxTessellator; + BoxGeometry.prototype = new Geometry(); + + return BoxGeometry; }); \ No newline at end of file diff --git a/Source/Core/ExtentTessellator.js b/Source/Core/ExtentTessellator.js index 3cfc152756ac..0939d80a7b76 100644 --- a/Source/Core/ExtentTessellator.js +++ b/Source/Core/ExtentTessellator.js @@ -25,11 +25,6 @@ define([ * Contains class functions to create a mesh or vertex array from a cartographic extent. * * @exports ExtentTessellator - * - * @see HeightmapTessellator - * @see EllipsoidGeometry - * @see BoxTessellator - * @see PlaneTessellator */ var ExtentTessellator = {}; diff --git a/Source/Core/GeometryFilters.js b/Source/Core/GeometryFilters.js index 462285d51c18..af9bc3b4f7b5 100644 --- a/Source/Core/GeometryFilters.js +++ b/Source/Core/GeometryFilters.js @@ -39,7 +39,7 @@ define([ * a primitive type of triangles, triangleStrip, or trangleFan is converted to a * list of indices with a primitive type of lines. Lists of indices with other primitive types remain unchanged. *

- * The mesh argument should use the standard layout like the mesh returned by {@link BoxTessellator}. + * The mesh argument should use the standard layout like the mesh returned by {@link BoxGeometry}. *

* This filter is commonly used to create a wireframe mesh for visual debugging. * @@ -47,10 +47,8 @@ define([ * * @returns The modified mesh argument, with its triangle indices converted to lines. * - * @see BoxTessellator - * * @example - * var mesh = BoxTessellator.compute(); + * var mesh = new BoxGeometry(); * mesh = GeometryFilters.toWireframe(mesh); */ GeometryFilters.toWireframe = function(mesh) { @@ -189,7 +187,7 @@ define([ * Reorders a mesh's indices to achieve better performance from the GPU's pre-vertex-shader cache. * Each list of indices in the mesh's indexList is reordered to keep the same index-vertex correspondence. *

- * The mesh argument should use the standard layout like the mesh returned by {@link BoxTessellator}. + * The mesh argument should use the standard layout like the mesh returned by {@link BoxGeometry}. *

* @param {Geometry} mesh The mesh to filter, which is modified in place. @@ -274,7 +272,7 @@ define([ * Reorders a mesh's indices to achieve better performance from the GPU's post vertex-shader cache by using the Tipsify algorithm. * Each list of indices in the mesh's indexList is optimally reordered. *

- * The mesh argument should use the standard layout like the mesh returned by {@link BoxTessellator}. + * The mesh argument should use the standard layout like the mesh returned by {@link BoxGeometry}. *

* @param {Geometry} mesh The mesh to filter, which is modified in place. diff --git a/Source/Core/HeightmapTessellator.js b/Source/Core/HeightmapTessellator.js index 922e82c3e8d4..7fbcc7630023 100644 --- a/Source/Core/HeightmapTessellator.js +++ b/Source/Core/HeightmapTessellator.js @@ -27,11 +27,6 @@ define([ * Contains functions to create a mesh from a heightmap image. * * @exports HeightmapTessellator - * - * @see ExtentTessellator - * @see EllipsoidGeometry - * @see BoxTessellator - * @see PlaneTessellator */ var HeightmapTessellator = {}; diff --git a/Source/Core/PlaneTessellator.js b/Source/Core/PlaneTessellator.js index 83f05973cff4..23443d36320d 100644 --- a/Source/Core/PlaneTessellator.js +++ b/Source/Core/PlaneTessellator.js @@ -15,9 +15,6 @@ define([ * DOC_TBA * * @exports PlaneTessellator - * - * @see EllipsoidGeometry - * @see BoxTessellator */ var PlaneTessellator = { /** diff --git a/Source/Renderer/Context.js b/Source/Renderer/Context.js index 0468a4d9be2a..d6ba144dfb3d 100644 --- a/Source/Renderer/Context.js +++ b/Source/Renderer/Context.js @@ -2326,7 +2326,7 @@ define([ * in system memory, whereas a vertex array contains vertex buffers and an optional index buffer in WebGL * memory for use with rendering. *

- * The mesh argument should use the standard layout like the mesh returned by {@link BoxTessellator}. + * The mesh argument should use the standard layout like the mesh returned by {@link BoxGeometry}. *

* creationArguments can have four properties: *
    @@ -2351,13 +2351,12 @@ define([ * @see Context#createIndexBuffer * @see GeometryFilters.createAttributeIndices * @see ShaderProgram - * @see BoxTessellator * * @example * // Example 1. Creates a vertex array for rendering a box. The default dynamic draw * // usage is used for the created vertex and index buffer. The attributes are not * // interleaved by default. - * var mesh = BoxTessellator.compute(); + * var mesh = new BoxGeometry(); * var va = context.createVertexArrayFromMesh({ * mesh : mesh, * attributeIndices : GeometryFilters.createAttributeIndices(mesh), diff --git a/Source/Scene/EllipsoidPrimitive.js b/Source/Scene/EllipsoidPrimitive.js index 228127859e56..31c244321eda 100644 --- a/Source/Scene/EllipsoidPrimitive.js +++ b/Source/Scene/EllipsoidPrimitive.js @@ -22,7 +22,7 @@ define([ '../Shaders/EllipsoidVS', '../Shaders/EllipsoidFS' ], function( - BoxTessellator, + BoxGeometry, Cartesian3, Cartesian4, combine, @@ -200,7 +200,7 @@ define([ return vertexArray; } - var mesh = BoxTessellator.compute({ + var mesh = new BoxGeometry({ dimensions : new Cartesian3(2.0, 2.0, 2.0) }); diff --git a/Source/Scene/SkyBox.js b/Source/Scene/SkyBox.js index 93a6cd2a3419..2d439c6b131e 100644 --- a/Source/Scene/SkyBox.js +++ b/Source/Scene/SkyBox.js @@ -15,7 +15,7 @@ define([ '../Shaders/SkyBoxVS', '../Shaders/SkyBoxFS' ], function( - BoxTessellator, + BoxGeometry, Cartesian3, destroyObject, DeveloperError, @@ -148,7 +148,7 @@ define([ } }; - var mesh = BoxTessellator.compute({ + var mesh = new BoxGeometry({ dimensions : new Cartesian3(2.0, 2.0, 2.0) }); var attributeIndices = GeometryFilters.createAttributeIndices(mesh); diff --git a/Source/Shaders/EllipsoidVS.glsl b/Source/Shaders/EllipsoidVS.glsl index 600a4969b2ba..b6821a8649b7 100644 --- a/Source/Shaders/EllipsoidVS.glsl +++ b/Source/Shaders/EllipsoidVS.glsl @@ -7,7 +7,7 @@ varying vec3 v_positionEC; void main() { // In the vertex data, the cube goes from (-1.0, -1.0, -1.0) to (1.0, 1.0, 1.0) in model coordinates. - // Scale to consider the radii. We could also do this once on the CPU when using the BoxTessellator, + // Scale to consider the radii. We could also do this once on the CPU when using the BoxGeometry, // but doing it here allows us to change the radii without rewriting the vertex data, and // allows all ellipsoids to reuse the same vertex data. vec4 p = vec4(u_radii * position, 1.0); diff --git a/Specs/Core/BoxGeometrySpec.js b/Specs/Core/BoxGeometrySpec.js index 2055632fb519..ff232e2a0050 100644 --- a/Specs/Core/BoxGeometrySpec.js +++ b/Specs/Core/BoxGeometrySpec.js @@ -3,21 +3,21 @@ defineSuite([ 'Core/BoxGeometry', 'Core/Cartesian3' ], function( - BoxTessellator, + BoxGeometry, Cartesian3) { "use strict"; /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/ it('compute0', function() { expect(function() { - return BoxTessellator.compute({ + return new BoxGeometry({ dimensions : new Cartesian3(1, 2, -1) }); }).toThrow(); }); it('compute1', function() { - var m = BoxTessellator.compute({ + var m = new BoxGeometry({ dimensions : new Cartesian3(1, 2, 3) }); @@ -27,7 +27,7 @@ defineSuite([ it('compute2', function() { expect(function() { - return BoxTessellator.compute({ + return new BoxGeometry({ minimumCorner : new Cartesian3(0, 0, 0), maximumCorner : new Cartesian3(1, 1, 1) }); diff --git a/Specs/Scene/MultifrustumSpec.js b/Specs/Scene/MultifrustumSpec.js index 98b6d0c8d006..3d16fad67404 100644 --- a/Specs/Scene/MultifrustumSpec.js +++ b/Specs/Scene/MultifrustumSpec.js @@ -26,7 +26,7 @@ defineSuite([ destroyScene, destroyObject, BoundingSphere, - BoxTessellator, + BoxGeometry, Cartesian2, Cartesian3, Color, @@ -212,7 +212,7 @@ defineSuite([ var dimensions = new Cartesian3(500000.0, 500000.0, 500000.0); var maximumCorner = dimensions.multiplyByScalar(0.5); var minimumCorner = maximumCorner.negate(); - var mesh = BoxTessellator.compute({ + var mesh = new BoxGeometry({ minimumCorner: minimumCorner, maximumCorner: maximumCorner }); From e4828ca8e5872c667bae6bd691ebd0b82e1261ea Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Thu, 9 May 2013 10:28:20 -0400 Subject: [PATCH 014/306] Start of vertex format --- Source/Core/BoxGeometry.js | 143 +++++++++++++++++++++++++++---------- 1 file changed, 106 insertions(+), 37 deletions(-) diff --git a/Source/Core/BoxGeometry.js b/Source/Core/BoxGeometry.js index 36cff4e4151c..bfadae907f95 100644 --- a/Source/Core/BoxGeometry.js +++ b/Source/Core/BoxGeometry.js @@ -21,6 +21,62 @@ define([ GeometryIndices) { "use strict"; +// TODO: move elsewhere + + /** + * DOC_TBA + * + * @alias GeometryVertexFormat + * @constructor + */ + var GeometryVertexFormat = function(options) { + options = defaultValue(options, defaultValue.EMPTY_OBJECT); + + /** + * DOC_TBA + */ + this.position = defaultValue(options.position, true); + + /** + * DOC_TBA + */ + this.normal = defaultValue(options.normal, true); + + /** + * DOC_TBA + */ + this.textureCoordinates = defaultValue(options.textureCoordinates, true); + + /** + * DOC_TBA + */ + this.binormal = defaultValue(options.binormal, false); + + /** + * DOC_TBA + */ + this.tangent = defaultValue(options.tangent, false); + }; + + // TODO: freezeObject + + /** + * DOC_TBA + */ + GeometryVertexFormat.DEFAULT = new GeometryVertexFormat(); + + /** + * DOC_TBA + */ + GeometryVertexFormat.POSITION_ONLY = new GeometryVertexFormat({ + normal : false, + textureCoordinates : false + }); + +///////////////////////////////////////////////////////////////// + + + /** * DOC_TBA * @@ -50,50 +106,63 @@ define([ maximumCorner = corner; } + var vertexFormat = defaultValue(options.vertexFormat, GeometryVertexFormat.DEFAULT); + + var attributes; + var indexLists; + +// if (vertexFormat !== GeometryVertexFormat.POSITION_ONLY) { +// } else { + // Positions only - no need to duplicate corner points + attributes = { + position : new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : [ + // 8 corner points. + minimumCorner.x, minimumCorner.y, minimumCorner.z, + maximumCorner.x, minimumCorner.y, minimumCorner.z, + maximumCorner.x, maximumCorner.y, minimumCorner.z, + minimumCorner.x, maximumCorner.y, minimumCorner.z, + minimumCorner.x, minimumCorner.y, maximumCorner.z, + maximumCorner.x, minimumCorner.y, maximumCorner.z, + maximumCorner.x, maximumCorner.y, maximumCorner.z, + minimumCorner.x, maximumCorner.y, maximumCorner.z + ] + }) + }; + + indexLists = [ + new GeometryIndices({ + // 12 triangles: 6 faces, 2 triangles each. + primitiveType : PrimitiveType.TRIANGLES, + values : [ + 4, 5, 6, // Top: plane z = corner.Z + 4, 6, 7, + 1, 0, 3, // Bottom: plane z = -corner.Z + 1, 3, 2, + 1, 6, 5, // Side: plane x = corner.X + 1, 2, 6, + 2, 3, 7, // Side: plane y = corner.Y + 2, 7, 6, + 3, 0, 4, // Side: plane x = -corner.X + 3, 4, 7, + 0, 1, 5, // Side: plane y = -corner.Y + 0, 5, 4 + ] + }) + ]; +// } + /** * DOC_TBA */ - this.attributes = { - position : new GeometryAttribute({ - componentDatatype : ComponentDatatype.FLOAT, - componentsPerAttribute : 3, - values : [ - // 8 corner points. - minimumCorner.x, minimumCorner.y, minimumCorner.z, - maximumCorner.x, minimumCorner.y, minimumCorner.z, - maximumCorner.x, maximumCorner.y, minimumCorner.z, - minimumCorner.x, maximumCorner.y, minimumCorner.z, - minimumCorner.x, minimumCorner.y, maximumCorner.z, - maximumCorner.x, minimumCorner.y, maximumCorner.z, - maximumCorner.x, maximumCorner.y, maximumCorner.z, - minimumCorner.x, maximumCorner.y, maximumCorner.z - ] - }) - }; + this.attributes = attributes; /** * DOC_TBA */ - this.indexLists = [ - new GeometryIndices({ - // 12 triangles: 6 faces, 2 triangles each. - primitiveType : PrimitiveType.TRIANGLES, - values : [ - 4, 5, 6, // Top: plane z = corner.Z - 4, 6, 7, - 1, 0, 3, // Bottom: plane z = -corner.Z - 1, 3, 2, - 1, 6, 5, // Side: plane x = corner.X - 1, 2, 6, - 2, 3, 7, // Side: plane y = corner.Y - 2, 7, 6, - 3, 0, 4, // Side: plane x = -corner.X - 3, 4, 7, - 0, 1, 5, // Side: plane y = -corner.Y - 0, 5, 4 - ] - }) - ]; + this.indexLists = indexLists; /** * DOC_TBA From 9547c07f58a817f6be02c6536e0ca48750d8dad4 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Fri, 10 May 2013 07:58:49 -0400 Subject: [PATCH 015/306] Added support for more than 64K vertices to the generic primitive --- Apps/CesiumViewer/CesiumViewer.js | 23 +++++++---- Source/Core/BoxGeometry.js | 66 +++---------------------------- Source/Core/EllipsoidGeometry.js | 2 + Source/Core/ExtentTessellator.js | 20 ++++++---- Source/Core/VertexFormat.js | 59 +++++++++++++++++++++++++++ Source/Scene/Primitive.js | 52 ++++++++++++++++-------- 6 files changed, 129 insertions(+), 93 deletions(-) create mode 100644 Source/Core/VertexFormat.js diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index a3103e401e93..98e14f2e2704 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -6,8 +6,12 @@ define([ 'dojo/parser', 'dojo/ready', 'Core/Math', + 'Core/Cartesian3', + 'Core/Ellipsoid', 'Core/Extent', 'Core/ExtentTessellator', + 'Core/EllipsoidGeometry', + 'Core/BoxGeometry', 'Core/GeometryFilters', 'Scene/Primitive', 'Scene/Appearance', @@ -20,8 +24,12 @@ define([ parser, ready, CesiumMath, + Cartesian3, + Ellipsoid, Extent, ExtentTessellator, + EllipsoidGeometry, + BoxGeometry, GeometryFilters, Primitive, Appearance, @@ -53,17 +61,16 @@ define([ CesiumMath.toRadians(-180.0), CesiumMath.toRadians(50.0), CesiumMath.toRadians(180.0), - CesiumMath.toRadians(90.0)) + CesiumMath.toRadians(90.0)), + granularity : 0.006 // More than 64K vertices }); - var anotherMesh = ExtentTessellator.compute({ - extent : new Extent( - CesiumMath.toRadians(-180.0), - CesiumMath.toRadians(10.0), - CesiumMath.toRadians(180.0), - CesiumMath.toRadians(30.0)) + var mesh2 = new EllipsoidGeometry(new Ellipsoid(8000000.0, 1000000.0, 1000000.0)); + + var mesh3 = new BoxGeometry({ + dimensions : new Cartesian3(100000.0, 100000.0, 15000000.0) }); - var primitive = new Primitive(GeometryFilters.combine([mesh, anotherMesh]), Appearance.EXAMPLE_APPEARANCE); + var primitive = new Primitive(GeometryFilters.combine([mesh, mesh2, mesh3]), Appearance.EXAMPLE_APPEARANCE); widget.scene.getPrimitives().add(primitive); domClass.remove(win.body(), 'loading'); diff --git a/Source/Core/BoxGeometry.js b/Source/Core/BoxGeometry.js index bfadae907f95..99e43856bafe 100644 --- a/Source/Core/BoxGeometry.js +++ b/Source/Core/BoxGeometry.js @@ -8,7 +8,8 @@ define([ './BoundingSphere', './Geometry', './GeometryAttribute', - './GeometryIndices' + './GeometryIndices', + './VertexFormat' ], function( DeveloperError, Cartesian3, @@ -18,65 +19,10 @@ define([ BoundingSphere, Geometry, GeometryAttribute, - GeometryIndices) { + GeometryIndices, + VertexFormat) { "use strict"; -// TODO: move elsewhere - - /** - * DOC_TBA - * - * @alias GeometryVertexFormat - * @constructor - */ - var GeometryVertexFormat = function(options) { - options = defaultValue(options, defaultValue.EMPTY_OBJECT); - - /** - * DOC_TBA - */ - this.position = defaultValue(options.position, true); - - /** - * DOC_TBA - */ - this.normal = defaultValue(options.normal, true); - - /** - * DOC_TBA - */ - this.textureCoordinates = defaultValue(options.textureCoordinates, true); - - /** - * DOC_TBA - */ - this.binormal = defaultValue(options.binormal, false); - - /** - * DOC_TBA - */ - this.tangent = defaultValue(options.tangent, false); - }; - - // TODO: freezeObject - - /** - * DOC_TBA - */ - GeometryVertexFormat.DEFAULT = new GeometryVertexFormat(); - - /** - * DOC_TBA - */ - GeometryVertexFormat.POSITION_ONLY = new GeometryVertexFormat({ - normal : false, - textureCoordinates : false - }); - -///////////////////////////////////////////////////////////////// - - - /** * DOC_TBA * @@ -106,12 +52,12 @@ define([ maximumCorner = corner; } - var vertexFormat = defaultValue(options.vertexFormat, GeometryVertexFormat.DEFAULT); + var vertexFormat = defaultValue(options.vertexFormat, VertexFormat.DEFAULT); var attributes; var indexLists; -// if (vertexFormat !== GeometryVertexFormat.POSITION_ONLY) { +// if (vertexFormat !== VertexFormat.POSITION_ONLY) { // } else { // Positions only - no need to duplicate corner points attributes = { diff --git a/Source/Core/EllipsoidGeometry.js b/Source/Core/EllipsoidGeometry.js index dc7dc9d06dd3..752c168deb51 100644 --- a/Source/Core/EllipsoidGeometry.js +++ b/Source/Core/EllipsoidGeometry.js @@ -30,6 +30,8 @@ define([ * @exception {DeveloperError} numberOfPartitions must be greater than zero. */ var EllipsoidGeometry = function(ellipsoid, numberOfPartitions, attributeName) { + numberOfPartitions = defaultValue(numberOfPartitions, 32); + if (numberOfPartitions <= 0) { throw new DeveloperError('numberOfPartitions must be greater than zero.'); } diff --git a/Source/Core/ExtentTessellator.js b/Source/Core/ExtentTessellator.js index 0939d80a7b76..5a29c6329f58 100644 --- a/Source/Core/ExtentTessellator.js +++ b/Source/Core/ExtentTessellator.js @@ -8,7 +8,9 @@ define([ './Extent', './Cartesian3', './ComponentDatatype', - './PrimitiveType' + './PrimitiveType', + './GeometryAttribute', + './GeometryIndices' ], function( clone, defaultValue, @@ -18,7 +20,9 @@ define([ Extent, Cartesian3, ComponentDatatype, - PrimitiveType) { + PrimitiveType, + GeometryAttribute, + GeometryIndices) { "use strict"; /** @@ -229,26 +233,26 @@ define([ var mesh = { attributes : {}, - indexLists : [{ + indexLists : [new GeometryIndices({ primitiveType : PrimitiveType.TRIANGLES, values : indices - }] + })] }; var positionName = defaultValue(description.positionName, 'position'); - mesh.attributes[positionName] = { + mesh.attributes[positionName] = new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 3, values : vertices - }; + }); if (description.generateTextureCoordinates) { var textureCoordinatesName = defaultValue(description.textureCoordinatesName, 'textureCoordinates'); - mesh.attributes[textureCoordinatesName] = { + mesh.attributes[textureCoordinatesName] = new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 2, values : textureCoordinates - }; + }); } return mesh; diff --git a/Source/Core/VertexFormat.js b/Source/Core/VertexFormat.js new file mode 100644 index 000000000000..1c627dc60356 --- /dev/null +++ b/Source/Core/VertexFormat.js @@ -0,0 +1,59 @@ +/*global define*/ +define([ + './defaultValue', + './freezeObject' + ], function( + defaultValue, + freezeObject) { + "use strict"; + + /** + * DOC_TBA + * + * @alias VertexFormat + * @constructor + */ + var VertexFormat = function(options) { + options = defaultValue(options, defaultValue.EMPTY_OBJECT); + + /** + * DOC_TBA + */ + this.position = defaultValue(options.position, true); + + /** + * DOC_TBA + */ + this.normal = defaultValue(options.normal, true); + + /** + * DOC_TBA + */ + this.textureCoordinates = defaultValue(options.textureCoordinates, true); + + /** + * DOC_TBA + */ + this.binormal = defaultValue(options.binormal, false); + + /** + * DOC_TBA + */ + this.tangent = defaultValue(options.tangent, false); + }; + + /** + * DOC_TBA + */ + VertexFormat.DEFAULT = freezeObject(new VertexFormat()); + + /** + * DOC_TBA + */ + VertexFormat.POSITION_ONLY = freezeObject(new VertexFormat({ + normal : false, + textureCoordinates : false + })); + + return VertexFormat; +}); \ No newline at end of file diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index d65c4ca7bb65..35bbc4de0cd9 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -70,26 +70,35 @@ define([ var attributeIndices = GeometryFilters.createAttributeIndices(this.mesh); var appearance = this.appearance; - this._va = context.createVertexArrayFromMesh({ - mesh : this.mesh, - attributeIndices : attributeIndices, - bufferUsage : BufferUsage.STATIC_DRAW, - vertexLayout : VertexLayout.INTERLEAVED - }); + // Break into multiple meshes to fit within unsigned short indices if needed + var meshes = GeometryFilters.fitToUnsignedShortIndices(this.mesh); + var va = []; + var length = meshes.length; + var i; + for (i = 0; i < length; ++i) { + va.push(context.createVertexArrayFromMesh({ + mesh : meshes[i], + attributeIndices : attributeIndices, + bufferUsage : BufferUsage.STATIC_DRAW, + vertexLayout : VertexLayout.INTERLEAVED + })); + } + + this._va = va; this._sp = context.getShaderCache().replaceShaderProgram(this._sp, appearance.vertexShaderSource, appearance.getFragmentShaderSource(), attributeIndices); this._rs = context.createRenderState(appearance.renderState); - var command = new DrawCommand(); + for (i = 0; i < length; ++i) { + var command = new DrawCommand(); // TODO: this assumes indices in the mesh - and only one set - command.primitiveType = this.mesh.indexLists[0].primitiveType; - command.vertexArray = this._va; - command.renderState = this._rs; - command.shaderProgram = this._sp; - command.uniformMap = appearance.material._uniforms; - command.boundingVolume = this.mesh.boundingSphere; -// command.boundingVolume = BoundingSphere.fromVertices(this.mesh.attributes.position.values); - - this._commands.push(command); + command.primitiveType = this.mesh.indexLists[0].primitiveType; + command.vertexArray = this._va[i]; + command.renderState = this._rs; + command.shaderProgram = this._sp; + command.uniformMap = appearance.material._uniforms; + command.boundingVolume = this.mesh.boundingSphere; + this._commands.push(command); + } } if (frameState.passes.color) { @@ -115,7 +124,16 @@ define([ */ Primitive.prototype.destroy = function() { this._sp = this._sp && this._sp.release(); - this._va = this._va && this._va.destroy(); + + var va = this._va; + if (typeof va !== 'undefined') { + var length = va.length; + for (var i = 0; i < length; ++i) { + va[i].destroy(); + } + this._va = undefined; + } + return destroyObject(this); }; From 8a1a6e56466641ce091d6508024b481ef0aae244 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Fri, 10 May 2013 10:20:07 -0400 Subject: [PATCH 016/306] Added support for per-geometry local coordinates --- Apps/CesiumViewer/CesiumViewer.js | 20 ++- Source/Core/BoxGeometry.js | 200 +++++++++++++++++++----- Source/Core/EllipsoidGeometry.js | 24 ++- Source/Core/ExtentTessellator.js | 6 +- Source/Core/Geometry.js | 11 +- Source/Core/GeometryFilters.js | 88 ++++++++++- Source/Scene/CentralBodySurface.js | 5 +- Source/Scene/SkyAtmosphere.js | 5 +- Source/Scene/SkyBox.js | 5 +- Source/Shaders/DefaultAppearanceFS.glsl | 10 +- Source/Shaders/DefaultAppearanceVS.glsl | 7 + Specs/Core/EllipsoidGeometrySpec.js | 19 ++- Specs/Core/GeometryFiltersSpec.js | 5 +- 13 files changed, 338 insertions(+), 67 deletions(-) diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index 98e14f2e2704..ff1fffa7946e 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -6,13 +6,16 @@ define([ 'dojo/parser', 'dojo/ready', 'Core/Math', + 'Core/Cartographic', 'Core/Cartesian3', + 'Core/Matrix4', 'Core/Ellipsoid', 'Core/Extent', 'Core/ExtentTessellator', 'Core/EllipsoidGeometry', 'Core/BoxGeometry', 'Core/GeometryFilters', + 'Core/Transforms', 'Scene/Primitive', 'Scene/Appearance', 'Widgets/Dojo/checkForChromeFrame', @@ -24,13 +27,16 @@ define([ parser, ready, CesiumMath, + Cartographic, Cartesian3, + Matrix4, Ellipsoid, Extent, ExtentTessellator, EllipsoidGeometry, BoxGeometry, GeometryFilters, + Transforms, Primitive, Appearance, checkForChromeFrame, @@ -64,13 +70,19 @@ define([ CesiumMath.toRadians(90.0)), granularity : 0.006 // More than 64K vertices }); - var mesh2 = new EllipsoidGeometry(new Ellipsoid(8000000.0, 1000000.0, 1000000.0)); - + var mesh2 = new EllipsoidGeometry({ + ellipsoid : new Ellipsoid(500000.0, 500000.0, 1000000.0), + modelMatrix : Matrix4.multiplyByTranslation(Transforms.eastNorthUpToFixedFrame( + Ellipsoid.WGS84.cartographicToCartesian(Cartographic.fromDegrees(-95.59777, 40.03883))), new Cartesian3(0.0, 0.0, 500000.0)) + }); var mesh3 = new BoxGeometry({ - dimensions : new Cartesian3(100000.0, 100000.0, 15000000.0) + dimensions : new Cartesian3(1000000.0, 1000000.0, 2000000.0), + modelMatrix : Matrix4.multiplyByTranslation(Transforms.eastNorthUpToFixedFrame( + Ellipsoid.WGS84.cartographicToCartesian(Cartographic.fromDegrees(-75.59777, 40.03883))), new Cartesian3(0.0, 0.0, 3000000.0)) }); - var primitive = new Primitive(GeometryFilters.combine([mesh, mesh2, mesh3]), Appearance.EXAMPLE_APPEARANCE); +// var primitive = new Primitive(GeometryFilters.combine([mesh, mesh2, mesh3]), Appearance.EXAMPLE_APPEARANCE); + var primitive = new Primitive(GeometryFilters.combine([mesh3]), Appearance.EXAMPLE_APPEARANCE); widget.scene.getPrimitives().add(primitive); domClass.remove(win.body(), 'loading'); diff --git a/Source/Core/BoxGeometry.js b/Source/Core/BoxGeometry.js index 99e43856bafe..0f7f0462aa5d 100644 --- a/Source/Core/BoxGeometry.js +++ b/Source/Core/BoxGeometry.js @@ -2,22 +2,22 @@ define([ './DeveloperError', './Cartesian3', + './Matrix4', './ComponentDatatype', './PrimitiveType', './defaultValue', './BoundingSphere', - './Geometry', './GeometryAttribute', './GeometryIndices', './VertexFormat' ], function( DeveloperError, Cartesian3, + Matrix4, ComponentDatatype, PrimitiveType, defaultValue, BoundingSphere, - Geometry, GeometryAttribute, GeometryIndices, VertexFormat) { @@ -34,12 +34,12 @@ define([ var BoxGeometry = function(options) { options = defaultValue(options, defaultValue.EMPTY_OBJECT); - var minimumCorner; - var maximumCorner; + var min; + var max; if (typeof options.minimumCorner !== 'undefined' && typeof options.maximumCorner !== 'undefined') { - minimumCorner = options.minimumCorner; - maximumCorner = options.maximumCorner; + min = options.minimumCorner; + max = options.maximumCorner; } else { var dimensions = typeof options.dimensions !== 'undefined' ? options.dimensions : new Cartesian3(1.0, 1.0, 1.0); @@ -48,57 +48,176 @@ define([ } var corner = dimensions.multiplyByScalar(0.5); - minimumCorner = corner.negate(); - maximumCorner = corner; + min = corner.negate(); + max = corner; } var vertexFormat = defaultValue(options.vertexFormat, VertexFormat.DEFAULT); - var attributes; - var indexLists; + var attributes = {}; + var indexLists = []; -// if (vertexFormat !== VertexFormat.POSITION_ONLY) { -// } else { - // Positions only - no need to duplicate corner points - attributes = { - position : new GeometryAttribute({ +// TODO: use typed arrays + + if (vertexFormat !== VertexFormat.POSITION_ONLY) { + + if (vertexFormat.position) { + // 8 corner points. Duplicated 3 times each for each incident edge/face. + attributes.position = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : [ + // +z face + min.x, min.y, max.z, + max.x, min.y, max.z, + max.x, max.y, max.z, + min.x, max.y, max.z, + + // -z face + min.x, min.y, min.z, + max.x, min.y, min.z, + max.x, max.y, min.z, + min.x, max.y, min.z, + + // +x face + max.x, min.y, min.z, + max.x, max.y, min.z, + max.x, max.y, max.z, + max.x, min.y, max.z, + + // -x face + min.x, min.y, min.z, + min.x, max.y, min.z, + min.x, max.y, max.z, + min.x, min.y, max.z, + + // +y face + min.x, max.y, min.z, + max.x, max.y, min.z, + max.x, max.y, max.z, + min.x, max.y, max.z, + + // -y face + min.x, min.y, min.z, + max.x, min.y, min.z, + max.x, min.y, max.z, + min.x, min.y, max.z + ] + }); + } + + if (vertexFormat.normal) { + attributes.normal = new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 3, values : [ - // 8 corner points. - minimumCorner.x, minimumCorner.y, minimumCorner.z, - maximumCorner.x, minimumCorner.y, minimumCorner.z, - maximumCorner.x, maximumCorner.y, minimumCorner.z, - minimumCorner.x, maximumCorner.y, minimumCorner.z, - minimumCorner.x, minimumCorner.y, maximumCorner.z, - maximumCorner.x, minimumCorner.y, maximumCorner.z, - maximumCorner.x, maximumCorner.y, maximumCorner.z, - minimumCorner.x, maximumCorner.y, maximumCorner.z + // +z face + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, + + // -z face + 0.0, 0.0, -1.0, + 0.0, 0.0, -1.0, + 0.0, 0.0, -1.0, + 0.0, 0.0, -1.0, + + // +x face + 1.0, 0.0, 0.0, + 1.0, 0.0, 0.0, + 1.0, 0.0, 0.0, + 1.0, 0.0, 0.0, + + // -x face + -1.0, 0.0, 0.0, + -1.0, 0.0, 0.0, + -1.0, 0.0, 0.0, + -1.0, 0.0, 0.0, + + // +y face + 0.0, 1.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 1.0, 0.0, + + // -y face + 0.0, -1.0, 0.0, + 0.0, -1.0, 0.0, + 0.0, -1.0, 0.0, + 0.0, -1.0, 0.0 ] - }) - }; + }); + } - indexLists = [ + indexLists.push( new GeometryIndices({ // 12 triangles: 6 faces, 2 triangles each. primitiveType : PrimitiveType.TRIANGLES, values : [ - 4, 5, 6, // Top: plane z = corner.Z + // +z face + 0, 1, 2, + 0, 2, 3, + + // -z face + 4 + 2, 4 + 1, 4 + 0, + 4 + 3, 4 + 2, 4 + 0, + + // +x face + 8 + 0, 8 + 1, 8 + 2, + 8 + 0, 8 + 2, 8 + 3, + + // -x face + 12 + 2, 12 + 1, 12 + 0, + 12 + 3, 12 + 2, 12 + 0, + + // +y face + 16 + 2, 16 + 1, 16 + 0, + 16 + 3, 16 + 2, 16 + 0, + + // -y face + 20 + 0, 20 + 1, 20 + 2, + 20 + 0, 20 + 2, 20 + 3, + ] + })); + } else { + // Positions only - no need to duplicate corner points + attributes.position = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : [ + // 8 corner points. + min.x, min.y, min.z, + max.x, min.y, min.z, + max.x, max.y, min.z, + min.x, max.y, min.z, + min.x, min.y, max.z, + max.x, min.y, max.z, + max.x, max.y, max.z, + min.x, max.y, max.z + ] + }); + + indexLists.push( + new GeometryIndices({ + // 12 triangles: 6 faces, 2 triangles each. + primitiveType : PrimitiveType.TRIANGLES, + values : [ + 4, 5, 6, // plane z = corner.Z 4, 6, 7, - 1, 0, 3, // Bottom: plane z = -corner.Z + 1, 0, 3, // plane z = -corner.Z 1, 3, 2, - 1, 6, 5, // Side: plane x = corner.X + 1, 6, 5, // plane x = corner.X 1, 2, 6, - 2, 3, 7, // Side: plane y = corner.Y + 2, 3, 7, // plane y = corner.Y 2, 7, 6, - 3, 0, 4, // Side: plane x = -corner.X + 3, 0, 4, // plane x = -corner.X 3, 4, 7, - 0, 1, 5, // Side: plane y = -corner.Y + 0, 1, 5, // plane y = -corner.Y 0, 5, 4 ] - }) - ]; -// } + })); + } /** * DOC_TBA @@ -113,10 +232,13 @@ define([ /** * DOC_TBA */ - this.boundingSphere = new BoundingSphere(new Cartesian3(), maximumCorner.subtract(minimumCorner).magnitude() * 0.5); - }; + this.boundingSphere = new BoundingSphere(new Cartesian3(), max.subtract(min).magnitude() * 0.5); - BoxGeometry.prototype = new Geometry(); + /** + * DOC_TBA + */ + this.modelMatrix = defaultValue(options.modelMatrix, Matrix4.IDENTITY.clone()); + }; return BoxGeometry; }); \ No newline at end of file diff --git a/Source/Core/EllipsoidGeometry.js b/Source/Core/EllipsoidGeometry.js index 752c168deb51..bf77a7e04cfe 100644 --- a/Source/Core/EllipsoidGeometry.js +++ b/Source/Core/EllipsoidGeometry.js @@ -3,20 +3,22 @@ define([ './defaultValue', './DeveloperError', './Cartesian3', + './Matrix4', + './Ellipsoid', './ComponentDatatype', './PrimitiveType', './BoundingSphere', - './Geometry', './GeometryAttribute', './GeometryIndices' ], function( defaultValue, DeveloperError, Cartesian3, + Matrix4, + Ellipsoid, ComponentDatatype, PrimitiveType, BoundingSphere, - Geometry, GeometryAttribute, GeometryIndices) { "use strict"; @@ -27,13 +29,16 @@ define([ * @alias EllipsoidGeometry * @constructor * - * @exception {DeveloperError} numberOfPartitions must be greater than zero. + * @exception {DeveloperError} options.numberOfPartitions must be greater than zero. */ - var EllipsoidGeometry = function(ellipsoid, numberOfPartitions, attributeName) { - numberOfPartitions = defaultValue(numberOfPartitions, 32); + var EllipsoidGeometry = function(options) { + options = defaultValue(options, defaultValue.EMPTY_OBJECT); + + var ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.UNIT_SPHERE); + var numberOfPartitions = defaultValue(options.numberOfPartitions, 32); if (numberOfPartitions <= 0) { - throw new DeveloperError('numberOfPartitions must be greater than zero.'); + throw new DeveloperError('options.numberOfPartitions must be greater than zero.'); } var positions = []; @@ -201,9 +206,12 @@ define([ * DOC_TBA */ this.boundingSphere = BoundingSphere.fromEllipsoid(ellipsoid); - }; - EllipsoidGeometry.prototype = new Geometry(); + /** + * DOC_TBA + */ + this.modelMatrix = defaultValue(options.modelMatrix, Matrix4.IDENTITY.clone()); + }; return EllipsoidGeometry; }); \ No newline at end of file diff --git a/Source/Core/ExtentTessellator.js b/Source/Core/ExtentTessellator.js index 5a29c6329f58..daae5eef0324 100644 --- a/Source/Core/ExtentTessellator.js +++ b/Source/Core/ExtentTessellator.js @@ -9,6 +9,7 @@ define([ './Cartesian3', './ComponentDatatype', './PrimitiveType', + './Geometry', './GeometryAttribute', './GeometryIndices' ], function( @@ -21,6 +22,7 @@ define([ Cartesian3, ComponentDatatype, PrimitiveType, + Geometry, GeometryAttribute, GeometryIndices) { "use strict"; @@ -231,13 +233,13 @@ define([ ExtentTessellator.computeVertices(computeVerticesDescription); - var mesh = { + var mesh = new Geometry({ attributes : {}, indexLists : [new GeometryIndices({ primitiveType : PrimitiveType.TRIANGLES, values : indices })] - }; + }); var positionName = defaultValue(description.positionName, 'position'); mesh.attributes[positionName] = new GeometryAttribute({ diff --git a/Source/Core/Geometry.js b/Source/Core/Geometry.js index 76a526ca3f2b..d1fc34f78b46 100644 --- a/Source/Core/Geometry.js +++ b/Source/Core/Geometry.js @@ -1,8 +1,10 @@ /*global define*/ define([ - './defaultValue' + './defaultValue', + './Matrix4', ], function( - defaultValue) { + defaultValue, + Matrix4) { "use strict"; /** @@ -28,6 +30,11 @@ define([ * DOC_TBA */ this.boundingSphere = options.boundingSphere; + + /** + * DOC_TBA + */ + this.modelMatrix = defaultValue(options.modelMatrix, Matrix4.IDENTITY.clone()); }; return Geometry; diff --git a/Source/Core/GeometryFilters.js b/Source/Core/GeometryFilters.js index af9bc3b4f7b5..ac51189eac07 100644 --- a/Source/Core/GeometryFilters.js +++ b/Source/Core/GeometryFilters.js @@ -4,6 +4,8 @@ define([ './DeveloperError', './Cartesian3', './EncodedCartesian3', + './Matrix3', + './Matrix4', './GeographicProjection', './ComponentDatatype', './PrimitiveType', @@ -16,6 +18,8 @@ define([ DeveloperError, Cartesian3, EncodedCartesian3, + Matrix3, + Matrix4, GeographicProjection, ComponentDatatype, PrimitiveType, @@ -614,6 +618,78 @@ define([ return attributesInAllMeshes; } + var scratch = new Cartesian3(); + + function transformPoint(matrix, attribute) { + if (typeof attribute !== 'undefined') { + var values = attribute.values; + var length = values.length; + for (var i = 0; i < length; i += 3) { + Cartesian3.fromArray(values, i, scratch); + Matrix4.multiplyByPoint(matrix, scratch, scratch); + values[i] = scratch.x; + values[i + 1] = scratch.y; + values[i + 2] = scratch.z; + } + } + } + + function transformVector(matrix, attribute) { + if (typeof attribute !== 'undefined') { + var values = attribute.values; + var length = values.length; + for (var i = 0; i < length; i += 3) { + Cartesian3.fromArray(values, i, scratch); + Matrix3.multiplyByVector(matrix, scratch, scratch); + values[i] = scratch.x; + values[i + 1] = scratch.y; + values[i + 2] = scratch.z; + } + } + } + + /** + * DOC_TBA + * + * @exception {DeveloperError} mesh is required. + */ + GeometryFilters.transformToWorldCoordinates = function(mesh) { + if (typeof mesh === 'undefined') { + throw new DeveloperError('mesh is required.'); + } + + if (mesh.modelMatrix.equals(Matrix4.IDENTITY)) { + // Already in world coordinates + return; + } + + var attributes = mesh.attributes; + + // Transform attributes in known vertex formats + transformPoint(mesh.modelMatrix, attributes.position); + + if ((typeof attributes.normal !== 'undefined') || + (typeof attributes.binormal !== 'undefined') || + (typeof attributes.tangent !== 'undefined')) { + + var inverseTranspose = new Matrix4(); + var normalMatrix = new Matrix3(); + Matrix4.inverse(mesh.modelMatrix, inverseTranspose); + Matrix4.transpose(inverseTranspose, inverseTranspose); + Matrix4.getRotation(inverseTranspose, normalMatrix); + + transformVector(normalMatrix, attributes.normal); + transformVector(normalMatrix, attributes.binormal); + transformVector(normalMatrix, attributes.tangent); + } + + if (typeof mesh.boundingSphere !== 'undefined') { + Matrix4.multiplyByPoint(mesh.modelMatrix, mesh.boundingSphere.center, mesh.boundingSphere.center); + } + + return mesh; + }; + /** * DOC_TBA * @@ -624,13 +700,19 @@ define([ throw new DeveloperError('meshes is required.'); } - if (meshes.length === 1) { + var length = meshes.length; + var i; + + // Unify to world coordinates before combining. + for (i = 0; i < length; ++i) { + GeometryFilters.transformToWorldCoordinates(meshes[i]); + } + + if (length === 1) { return meshes[0]; } - var length = meshes.length; var name; - var i; var j; var k; diff --git a/Source/Scene/CentralBodySurface.js b/Source/Scene/CentralBodySurface.js index 5dbdd70b5a51..29284070e4eb 100644 --- a/Source/Scene/CentralBodySurface.js +++ b/Source/Scene/CentralBodySurface.js @@ -722,7 +722,10 @@ define([ if (typeof surface._debug !== 'undefined' && typeof surface._debug.boundingSphereTile !== 'undefined') { if (!surface._debug.boundingSphereVA) { var radius = surface._debug.boundingSphereTile.boundingSphere3D.radius; - var sphere = new EllipsoidGeometry(new Ellipsoid(radius, radius, radius), 10); + var sphere = new EllipsoidGeometry({ + ellipsoid : new Ellipsoid(radius, radius, radius), + numberOfPartitions : 10 + }); GeometryFilters.toWireframe(sphere); surface._debug.boundingSphereVA = context.createVertexArrayFromMesh({ mesh : sphere, diff --git a/Source/Scene/SkyAtmosphere.js b/Source/Scene/SkyAtmosphere.js index 7a6d5dca448f..29a47fc63b6d 100644 --- a/Source/Scene/SkyAtmosphere.js +++ b/Source/Scene/SkyAtmosphere.js @@ -133,7 +133,10 @@ define([ var command = this._command; if (typeof command.vertexArray === 'undefined') { - var mesh = new EllipsoidGeometry(Ellipsoid.fromCartesian3(this._ellipsoid.getRadii().multiplyByScalar(1.025)), 60); + var mesh = new EllipsoidGeometry({ + ellipsoid : Ellipsoid.fromCartesian3(this._ellipsoid.getRadii().multiplyByScalar(1.025)), + numberOfPartitions : 60 + }); command.vertexArray = context.createVertexArrayFromMesh({ mesh : mesh, attributeIndices : GeometryFilters.createAttributeIndices(mesh), diff --git a/Source/Scene/SkyBox.js b/Source/Scene/SkyBox.js index 2d439c6b131e..6bd89fe10bb6 100644 --- a/Source/Scene/SkyBox.js +++ b/Source/Scene/SkyBox.js @@ -6,6 +6,7 @@ define([ '../Core/DeveloperError', '../Core/Matrix4', '../Core/GeometryFilters', + '../Core/VertexFormat', '../Core/PrimitiveType', '../Renderer/loadCubeMap', '../Renderer/BufferUsage', @@ -21,6 +22,7 @@ define([ DeveloperError, Matrix4, GeometryFilters, + VertexFormat, PrimitiveType, loadCubeMap, BufferUsage, @@ -149,7 +151,8 @@ define([ }; var mesh = new BoxGeometry({ - dimensions : new Cartesian3(2.0, 2.0, 2.0) + dimensions : new Cartesian3(2.0, 2.0, 2.0), + vertexFormat : VertexFormat.POSITION_ONLY }); var attributeIndices = GeometryFilters.createAttributeIndices(mesh); diff --git a/Source/Shaders/DefaultAppearanceFS.glsl b/Source/Shaders/DefaultAppearanceFS.glsl index 478683d7b721..99402abde84f 100644 --- a/Source/Shaders/DefaultAppearanceFS.glsl +++ b/Source/Shaders/DefaultAppearanceFS.glsl @@ -1,7 +1,15 @@ +varying vec3 v_normalEC; +varying vec3 v_positionEC; + void main() { + vec3 positionToEyeEC = -v_positionEC; + czm_materialInput materialInput; - + materialInput.normalEC = v_normalEC; + materialInput.positionToEyeEC = positionToEyeEC; czm_material material = czm_getMaterial(materialInput); + +// gl_FragColor = czm_phong(normalize(positionToEyeEC), material); gl_FragColor = vec4(material.diffuse + material.emission, material.alpha); } diff --git a/Source/Shaders/DefaultAppearanceVS.glsl b/Source/Shaders/DefaultAppearanceVS.glsl index 971641636b49..fe4415aa709a 100644 --- a/Source/Shaders/DefaultAppearanceVS.glsl +++ b/Source/Shaders/DefaultAppearanceVS.glsl @@ -1,6 +1,13 @@ attribute vec4 position; +attribute vec3 normal; + +varying vec3 v_normalEC; +varying vec3 v_positionEC; void main() { + v_normalEC = czm_normal * normal; // normal in eye coordinates + v_positionEC = (czm_modelView * position).xyz; // position in eye coordinates + gl_Position = czm_modelViewProjection * position; } diff --git a/Specs/Core/EllipsoidGeometrySpec.js b/Specs/Core/EllipsoidGeometrySpec.js index c3130c36d954..60c57df05b60 100644 --- a/Specs/Core/EllipsoidGeometrySpec.js +++ b/Specs/Core/EllipsoidGeometrySpec.js @@ -14,12 +14,17 @@ defineSuite([ it('compute0', function() { expect(function() { - return new EllipsoidGeometry(Ellipsoid.UNIT_SPHERE, -1); + return new EllipsoidGeometry({ + numberOfPartitions : -1 + }); }).toThrow(); }); it('compute1', function() { - var m = new EllipsoidGeometry(Ellipsoid.UNIT_SPHERE, 1); + var m = new EllipsoidGeometry({ + ellipsoid : Ellipsoid.UNIT_SPHERE, + numberOfPartitions : 1 + }); expect(m.attributes.position.values.length).toEqual(3 * 8); expect(m.indexLists[0].values.length).toEqual(12 * 3); @@ -27,14 +32,20 @@ defineSuite([ }); it('compute2', function() { - var m = new EllipsoidGeometry(Ellipsoid.UNIT_SPHERE, 2); + var m = new EllipsoidGeometry({ + ellipsoid : Ellipsoid.UNIT_SPHERE, + numberOfPartitions : 2 + }); expect(m.attributes.position.values.length).toEqual(3 * (8 + 6 + 12)); expect(m.indexLists[0].values.length).toEqual(2 * 3 * 4 * 6); }); it('compute3', function() { - var m = new EllipsoidGeometry(Ellipsoid.UNIT_SPHERE, 3); + var m = new EllipsoidGeometry({ + ellipsoid : Ellipsoid.UNIT_SPHERE, + numberOfPartitions : 3 + }); var position = m.attributes.position.values; for ( var i = 0; i < position.length; i += 3) { diff --git a/Specs/Core/GeometryFiltersSpec.js b/Specs/Core/GeometryFiltersSpec.js index fd632d01a3b4..73a3587e43af 100644 --- a/Specs/Core/GeometryFiltersSpec.js +++ b/Specs/Core/GeometryFiltersSpec.js @@ -239,7 +239,10 @@ defineSuite([ }); it('can reorder indices for the post vertex cache', function() { - var mesh = new EllipsoidGeometry(new Ellipsoid(10.0, 10.0, 10.0), 100); + var mesh = new EllipsoidGeometry({ + ellipsoid : new Ellipsoid(10.0, 10.0, 10.0), + numberOfPartitions : 100 + }); var indices = mesh.indexLists[0].values; var numIndices = indices.length; var maximumIndex = 0; From 3cf34a2f717e2eee38d822e0884114e34bcf9501 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Fri, 10 May 2013 11:00:25 -0400 Subject: [PATCH 017/306] Added texture coordinates to box --- Apps/CesiumViewer/CesiumViewer.js | 28 +++++++++++++-- Source/Core/BoxGeometry.js | 45 +++++++++++++++++++++++++ Source/Core/VertexFormat.js | 4 +-- Source/Scene/Appearance.js | 21 +++++++----- Source/Shaders/DefaultAppearanceFS.glsl | 2 ++ Source/Shaders/DefaultAppearanceVS.glsl | 3 ++ 6 files changed, 90 insertions(+), 13 deletions(-) diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index ff1fffa7946e..4789508b8737 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -18,6 +18,7 @@ define([ 'Core/Transforms', 'Scene/Primitive', 'Scene/Appearance', + 'Scene/Material', 'Widgets/Dojo/checkForChromeFrame', 'Widgets/Dojo/CesiumViewerWidget' ], function( @@ -39,6 +40,7 @@ define([ Transforms, Primitive, Appearance, + Material, checkForChromeFrame, CesiumViewerWidget) { "use strict"; @@ -81,8 +83,30 @@ define([ Ellipsoid.WGS84.cartographicToCartesian(Cartographic.fromDegrees(-75.59777, 40.03883))), new Cartesian3(0.0, 0.0, 3000000.0)) }); -// var primitive = new Primitive(GeometryFilters.combine([mesh, mesh2, mesh3]), Appearance.EXAMPLE_APPEARANCE); - var primitive = new Primitive(GeometryFilters.combine([mesh3]), Appearance.EXAMPLE_APPEARANCE); + var primitive = new Primitive(GeometryFilters.combine([mesh, mesh2, mesh3]), Appearance.CLOSED_TRANSLUCENT); + +/* + var m = new Material({ + context : widget.scene.getContext(), + fabric : { + type : 'Image', + uniforms : { + image : '../Sandcastle/images/Cesium_Logo_Color.jpg' + } + } + }); + var rs = { + depthTest : { + enabled : true + } + }; + var appearance = new Appearance({ + material : m, + renderState : rs + }); + var primitive = new Primitive(GeometryFilters.combine([mesh3]), appearance); +*/ + widget.scene.getPrimitives().add(primitive); domClass.remove(win.body(), 'loading'); diff --git a/Source/Core/BoxGeometry.js b/Source/Core/BoxGeometry.js index 0f7f0462aa5d..7d8e0c4d105c 100644 --- a/Source/Core/BoxGeometry.js +++ b/Source/Core/BoxGeometry.js @@ -150,6 +150,51 @@ define([ }); } + + if (vertexFormat.st) { + attributes.st = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 2, + values : [ + // +z face + 0.0, 0.0, + 1.0, 0.0, + 1.0, 1.0, + 0.0, 1.0, + + // -z face + 1.0, 0.0, + 0.0, 0.0, + 0.0, 1.0, + 1.0, 1.0, + + // +x face + 0.0, 0.0, + 1.0, 0.0, + 1.0, 1.0, + 0.0, 1.0, + + // -x face + 1.0, 0.0, + 0.0, 0.0, + 0.0, 1.0, + 1.0, 1.0, + + // +y face + 1.0, 0.0, + 0.0, 0.0, + 0.0, 1.0, + 1.0, 1.0, + + // -y face + 0.0, 0.0, + 1.0, 0.0, + 1.0, 1.0, + 0.0, 1.0 + ] + }); + } + indexLists.push( new GeometryIndices({ // 12 triangles: 6 faces, 2 triangles each. diff --git a/Source/Core/VertexFormat.js b/Source/Core/VertexFormat.js index 1c627dc60356..94589be783de 100644 --- a/Source/Core/VertexFormat.js +++ b/Source/Core/VertexFormat.js @@ -29,7 +29,7 @@ define([ /** * DOC_TBA */ - this.textureCoordinates = defaultValue(options.textureCoordinates, true); + this.st = defaultValue(options.textureCoordinates, true); /** * DOC_TBA @@ -51,7 +51,7 @@ define([ * DOC_TBA */ VertexFormat.POSITION_ONLY = freezeObject(new VertexFormat({ - normal : false, + st : false, textureCoordinates : false })); diff --git a/Source/Scene/Appearance.js b/Source/Scene/Appearance.js index 7b9ea9b7d8ae..f2ee9f707610 100644 --- a/Source/Scene/Appearance.js +++ b/Source/Scene/Appearance.js @@ -1,5 +1,6 @@ /*global define*/ define([ + '../Core/defaultValue', '../Core/freezeObject', '../Renderer/CullFace', '../Renderer/BlendingState', @@ -7,6 +8,7 @@ define([ '../Shaders/DefaultAppearanceVS', '../Shaders/DefaultAppearanceFS' ], function( + defaultValue, freezeObject, CullFace, BlendingState, @@ -19,26 +21,27 @@ define([ * DOC_TBA */ var Appearance = function(options) { -// TODO: throw without options + options = defaultValue(options, defaultValue.EMPTY_OBJECT); + /** * DOC_TBA */ - this.material = options.material; + this.material = (typeof options.material !== 'undefined') ? options.material : Material.fromType(undefined, Material.ColorType); /** * DOC_TBA */ - this.vertexShaderSource = options.vertexShaderSource; + this.vertexShaderSource = defaultValue(options.vertexShaderSource, DefaultAppearanceVS); /** * DOC_TBA */ - this.fragmentShaderSource = options.fragmentShaderSource; + this.fragmentShaderSource = defaultValue(options.fragmentShaderSource, DefaultAppearanceFS); /** * DOC_TBA */ - this.renderState = options.renderState; + this.renderState = defaultValue(options.renderState, {}); }; /** @@ -51,10 +54,10 @@ define([ this.fragmentShaderSource; }; - Appearance.EXAMPLE_APPEARANCE = freezeObject(new Appearance({ - material : Material.fromType(undefined, Material.ColorType), - vertexShaderSource : DefaultAppearanceVS, - fragmentShaderSource : DefaultAppearanceFS, + /** + * DOC_TBA + */ + Appearance.CLOSED_TRANSLUCENT = freezeObject(new Appearance({ renderState : { cull : { enabled : true, diff --git a/Source/Shaders/DefaultAppearanceFS.glsl b/Source/Shaders/DefaultAppearanceFS.glsl index 99402abde84f..346f8e3334b3 100644 --- a/Source/Shaders/DefaultAppearanceFS.glsl +++ b/Source/Shaders/DefaultAppearanceFS.glsl @@ -1,5 +1,6 @@ varying vec3 v_normalEC; varying vec3 v_positionEC; +varying vec2 v_st; void main() { @@ -8,6 +9,7 @@ void main() czm_materialInput materialInput; materialInput.normalEC = v_normalEC; materialInput.positionToEyeEC = positionToEyeEC; + materialInput.st = v_st; czm_material material = czm_getMaterial(materialInput); // gl_FragColor = czm_phong(normalize(positionToEyeEC), material); diff --git a/Source/Shaders/DefaultAppearanceVS.glsl b/Source/Shaders/DefaultAppearanceVS.glsl index fe4415aa709a..6c3501e57e0c 100644 --- a/Source/Shaders/DefaultAppearanceVS.glsl +++ b/Source/Shaders/DefaultAppearanceVS.glsl @@ -1,13 +1,16 @@ attribute vec4 position; attribute vec3 normal; +attribute vec2 st; varying vec3 v_normalEC; varying vec3 v_positionEC; +varying vec2 v_st; void main() { v_normalEC = czm_normal * normal; // normal in eye coordinates v_positionEC = (czm_modelView * position).xyz; // position in eye coordinates + v_st = st; gl_Position = czm_modelViewProjection * position; } From c7bfb26fb3d6a57946a126e60bd58c9853ced417 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Fri, 10 May 2013 12:17:05 -0400 Subject: [PATCH 018/306] Cleaned geometry filters --- Apps/CesiumViewer/CesiumViewer.js | 4 +-- Source/Core/GeometryFilters.js | 43 ++++++++++++++++++++++------ Source/Scene/Primitive.js | 47 ++++++++++++++++++++----------- 3 files changed, 67 insertions(+), 27 deletions(-) diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index 4789508b8737..edd057e5be56 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -83,7 +83,7 @@ define([ Ellipsoid.WGS84.cartographicToCartesian(Cartographic.fromDegrees(-75.59777, 40.03883))), new Cartesian3(0.0, 0.0, 3000000.0)) }); - var primitive = new Primitive(GeometryFilters.combine([mesh, mesh2, mesh3]), Appearance.CLOSED_TRANSLUCENT); + var primitive = new Primitive([mesh, mesh2, mesh3], Appearance.CLOSED_TRANSLUCENT); /* var m = new Material({ @@ -104,7 +104,7 @@ define([ material : m, renderState : rs }); - var primitive = new Primitive(GeometryFilters.combine([mesh3]), appearance); + var primitive = new Primitive(mesh3, appearance); */ widget.scene.getPrimitives().add(primitive); diff --git a/Source/Core/GeometryFilters.js b/Source/Core/GeometryFilters.js index ac51189eac07..2888fd24f973 100644 --- a/Source/Core/GeometryFilters.js +++ b/Source/Core/GeometryFilters.js @@ -10,6 +10,7 @@ define([ './ComponentDatatype', './PrimitiveType', './Tipsify', + './BoundingSphere', './Geometry', './GeometryAttribute', './GeometryIndices' @@ -24,6 +25,7 @@ define([ ComponentDatatype, PrimitiveType, Tipsify, + BoundingSphere, Geometry, GeometryAttribute, GeometryIndices) { @@ -687,6 +689,8 @@ define([ Matrix4.multiplyByPoint(mesh.modelMatrix, mesh.boundingSphere.center, mesh.boundingSphere.center); } + mesh.modelMatrix = Matrix4.IDENTITY.clone(); + return mesh; }; @@ -694,28 +698,31 @@ define([ * DOC_TBA * * @exception {DeveloperError} meshes is required and must have length greater than zero. + * @exception {DeveloperError} All meshes must have the same modelMatrix. */ GeometryFilters.combine = function(meshes) { if ((typeof meshes === 'undefined') || (meshes.length < 1)) { - throw new DeveloperError('meshes is required.'); + throw new DeveloperError('meshes is required and must have length greater than zero.'); } var length = meshes.length; - var i; - - // Unify to world coordinates before combining. - for (i = 0; i < length; ++i) { - GeometryFilters.transformToWorldCoordinates(meshes[i]); - } if (length === 1) { return meshes[0]; } var name; + var i; var j; var k; + var m = meshes[0].modelMatrix; + for (i = 1; i < length; ++i) { + if (!Matrix4.equals(meshes[i].modelMatrix, m)) { + throw new DeveloperError('All meshes must have the same modelMatrix.'); + } + } + // Find subset of attributes in all meshes var attributes = findAttributesInAllMeshes(meshes); @@ -817,10 +824,28 @@ define([ } } -// TODO: combine bounding spheres + // Create bounding sphere that includes all meshes + var boundingSphere = undefined; + + for (i = 0; i < length; ++i) { + var bs = meshes[i].boundingSphere; + if (typeof bs === 'undefined') { + // If any meshes have an undefined bounding sphere, then so does the combined mesh + boundingSphere = undefined; + break; + } + + if (typeof boundingSphere === 'undefined') { + boundingSphere = bs.clone(); + } else { + BoundingSphere.union(boundingSphere, bs, boundingSphere); + } + } + return new Geometry({ attributes : attributes, - indexLists : combinedIndexLists + indexLists : combinedIndexLists, + boundingSphere : boundingSphere }); }; diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index 35bbc4de0cd9..7101bac4d5c9 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -26,11 +26,11 @@ define([ /** * DOC_TBA */ - var Primitive = function(mesh, appearance) { + var Primitive = function(meshes, appearance) { /** * DOC_TBA */ - this.mesh = mesh; + this.meshes = meshes; /** * DOC_TBA @@ -51,10 +51,21 @@ define([ this._rs = undefined; this._va = undefined; - this._commands = []; this._commandLists = new CommandLists(); }; + function processGeometry(geometries) { + // Unify to world coordinates before combining. + var length = geometries.length; + for (var i = 0; i < length; ++i) { + GeometryFilters.transformToWorldCoordinates(geometries[i]); + } + + var geometry = GeometryFilters.combine(geometries); + + return geometry; + } + /** * @private */ @@ -64,14 +75,16 @@ define([ return; } -// TODO: throw if mesh and appearance are not defined +// TODO: throw if meshes and appearance are not defined - if (typeof this._va === 'undefined') { - var attributeIndices = GeometryFilters.createAttributeIndices(this.mesh); - var appearance = this.appearance; + var colorCommands = this._commandLists.colorList; + if (typeof this._va === 'undefined') { + var mesh = processGeometry(this.meshes); // Break into multiple meshes to fit within unsigned short indices if needed - var meshes = GeometryFilters.fitToUnsignedShortIndices(this.mesh); + var meshes = GeometryFilters.fitToUnsignedShortIndices(mesh); + var attributeIndices = GeometryFilters.createAttributeIndices(mesh); + var va = []; var length = meshes.length; var i; @@ -84,29 +97,31 @@ define([ })); } + var appearance = this.appearance; + this._va = va; this._sp = context.getShaderCache().replaceShaderProgram(this._sp, appearance.vertexShaderSource, appearance.getFragmentShaderSource(), attributeIndices); this._rs = context.createRenderState(appearance.renderState); for (i = 0; i < length; ++i) { var command = new DrawCommand(); -// TODO: this assumes indices in the mesh - and only one set - command.primitiveType = this.mesh.indexLists[0].primitiveType; +// TODO: this assumes indices in the meshes - and only one set + command.primitiveType = mesh.indexLists[0].primitiveType; command.vertexArray = this._va[i]; command.renderState = this._rs; command.shaderProgram = this._sp; command.uniformMap = appearance.material._uniforms; - command.boundingVolume = this.mesh.boundingSphere; - this._commands.push(command); +// TODO: could use bounding volume per mesh + command.boundingVolume = mesh.boundingSphere; + colorCommands.push(command); } } if (frameState.passes.color) { - var commands = this._commands; - var len = commands.length; + // The geometry is static but the model matrix can change + var len = colorCommands.length; for (var i = 0; i < len; ++i) { - commands[i].modelMatrix = this.modelMatrix; - this._commandLists.colorList[i] = commands[i]; + colorCommands[i].modelMatrix = this.modelMatrix; } commandList.push(this._commandLists); } From c1840f3778da487b9ecef4d8b4bf666e9d664dc2 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Fri, 10 May 2013 17:09:29 -0400 Subject: [PATCH 019/306] Added picking to generic primitive --- Apps/CesiumViewer/CesiumViewer.js | 30 ++++- Source/Core/BoxGeometry.js | 5 + Source/Core/EllipsoidGeometry.js | 5 + Source/Core/Geometry.js | 29 +++++ Source/Core/GeometryFilters.js | 1 + Source/Core/VertexFormat.js | 2 + Source/Renderer/PickFramebuffer.js | 3 + Source/Scene/Appearance.js | 4 + Source/Scene/Primitive.js | 155 +++++++++++++++++++----- Source/Shaders/DefaultAppearanceFS.glsl | 14 +-- Source/Shaders/DefaultAppearanceVS.glsl | 19 +-- 11 files changed, 222 insertions(+), 45 deletions(-) diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index edd057e5be56..dce4a09cc6fb 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -15,7 +15,10 @@ define([ 'Core/EllipsoidGeometry', 'Core/BoxGeometry', 'Core/GeometryFilters', + 'Core/VertexFormat', 'Core/Transforms', + 'Core/ScreenSpaceEventHandler', + 'Core/ScreenSpaceEventType', 'Scene/Primitive', 'Scene/Appearance', 'Scene/Material', @@ -37,7 +40,10 @@ define([ EllipsoidGeometry, BoxGeometry, GeometryFilters, + VertexFormat, Transforms, + ScreenSpaceEventHandler, + ScreenSpaceEventType, Primitive, Appearance, Material, @@ -64,6 +70,8 @@ define([ widget.startup(); widget.fullscreen.viewModel.fullscreenElement(document.body); + var scene = widget.scene; + var mesh = ExtentTessellator.compute({ extent : new Extent( CesiumMath.toRadians(-180.0), @@ -72,15 +80,21 @@ define([ CesiumMath.toRadians(90.0)), granularity : 0.006 // More than 64K vertices }); + mesh.pickData = 'mesh'; + var mesh2 = new EllipsoidGeometry({ ellipsoid : new Ellipsoid(500000.0, 500000.0, 1000000.0), modelMatrix : Matrix4.multiplyByTranslation(Transforms.eastNorthUpToFixedFrame( - Ellipsoid.WGS84.cartographicToCartesian(Cartographic.fromDegrees(-95.59777, 40.03883))), new Cartesian3(0.0, 0.0, 500000.0)) + Ellipsoid.WGS84.cartographicToCartesian(Cartographic.fromDegrees(-95.59777, 40.03883))), new Cartesian3(0.0, 0.0, 500000.0)), + pickData : 'mesh2' }); + var mesh3 = new BoxGeometry({ + vertexFormat : VertexFormat.POSITION_ONLY, dimensions : new Cartesian3(1000000.0, 1000000.0, 2000000.0), modelMatrix : Matrix4.multiplyByTranslation(Transforms.eastNorthUpToFixedFrame( - Ellipsoid.WGS84.cartographicToCartesian(Cartographic.fromDegrees(-75.59777, 40.03883))), new Cartesian3(0.0, 0.0, 3000000.0)) + Ellipsoid.WGS84.cartographicToCartesian(Cartographic.fromDegrees(-75.59777, 40.03883))), new Cartesian3(0.0, 0.0, 3000000.0)), + pickData : 'mesh3' }); var primitive = new Primitive([mesh, mesh2, mesh3], Appearance.CLOSED_TRANSLUCENT); @@ -109,6 +123,18 @@ define([ widget.scene.getPrimitives().add(primitive); + + var handler = new ScreenSpaceEventHandler(scene.getCanvas()); + handler.setInputAction( + function (movement) { + var pickedObject = scene.pick(movement.endPosition); + if (typeof pickedObject !== 'undefined') { + console.log(pickedObject); + } + }, + ScreenSpaceEventType.MOUSE_MOVE + ); + domClass.remove(win.body(), 'loading'); }); }); \ No newline at end of file diff --git a/Source/Core/BoxGeometry.js b/Source/Core/BoxGeometry.js index 7d8e0c4d105c..5811dc8f039f 100644 --- a/Source/Core/BoxGeometry.js +++ b/Source/Core/BoxGeometry.js @@ -283,6 +283,11 @@ define([ * DOC_TBA */ this.modelMatrix = defaultValue(options.modelMatrix, Matrix4.IDENTITY.clone()); + + /** + * DOC_TBA + */ + this.pickData = options.pickData; }; return BoxGeometry; diff --git a/Source/Core/EllipsoidGeometry.js b/Source/Core/EllipsoidGeometry.js index bf77a7e04cfe..b628f3cad72b 100644 --- a/Source/Core/EllipsoidGeometry.js +++ b/Source/Core/EllipsoidGeometry.js @@ -211,6 +211,11 @@ define([ * DOC_TBA */ this.modelMatrix = defaultValue(options.modelMatrix, Matrix4.IDENTITY.clone()); + + /** + * DOC_TBA + */ + this.pickData = options.pickData; }; return EllipsoidGeometry; diff --git a/Source/Core/Geometry.js b/Source/Core/Geometry.js index d1fc34f78b46..1c8706e97d6b 100644 --- a/Source/Core/Geometry.js +++ b/Source/Core/Geometry.js @@ -1,9 +1,11 @@ /*global define*/ define([ './defaultValue', + './DeveloperError', './Matrix4', ], function( defaultValue, + DeveloperError, Matrix4) { "use strict"; @@ -35,6 +37,33 @@ define([ * DOC_TBA */ this.modelMatrix = defaultValue(options.modelMatrix, Matrix4.IDENTITY.clone()); + + /** + * DOC_TBA + */ + this.pickData = options.pickData; + }; + + /** + * DOC_TBA + * + * @exception {DeveloperError} geometries is required. + */ + Geometry.isPickable = function(geometries) { + if (typeof geometries === 'undefined') { + throw new DeveloperError('geometries is required.'); + } + + var pickable = false; + var length = geometries.length; + for (var i = 0; i < length; ++i) { + if (typeof geometries[i].pickData !== 'undefined') { + pickable = true; + break; + } + } + + return pickable; }; return Geometry; diff --git a/Source/Core/GeometryFilters.js b/Source/Core/GeometryFilters.js index 2888fd24f973..8fc03fd48550 100644 --- a/Source/Core/GeometryFilters.js +++ b/Source/Core/GeometryFilters.js @@ -344,6 +344,7 @@ define([ newAttributes[attribute] = new GeometryAttribute({ componentDatatype : attr.componentDatatype, componentsPerAttribute : attr.componentsPerAttribute, + normalize : attr.normalize, values : [] }); } diff --git a/Source/Core/VertexFormat.js b/Source/Core/VertexFormat.js index 94589be783de..f594f6f8351c 100644 --- a/Source/Core/VertexFormat.js +++ b/Source/Core/VertexFormat.js @@ -40,6 +40,8 @@ define([ * DOC_TBA */ this.tangent = defaultValue(options.tangent, false); + + // pickColor is also a reserved name added, when needed, for picking. }; /** diff --git a/Source/Renderer/PickFramebuffer.js b/Source/Renderer/PickFramebuffer.js index 910f579b2ef8..606bf0632a71 100644 --- a/Source/Renderer/PickFramebuffer.js +++ b/Source/Renderer/PickFramebuffer.js @@ -90,6 +90,9 @@ define([ framebuffer : this._fb }); +// TODO: remove +console.log(pixels[0] + ', ' + pixels[1] + ', ' + pixels[2] + ', ' + pixels[3]); + var max = Math.max(width, height); var length = max * max; var halfWidth = Math.floor(width * 0.5); diff --git a/Source/Scene/Appearance.js b/Source/Scene/Appearance.js index f2ee9f707610..ae6f1a5aab18 100644 --- a/Source/Scene/Appearance.js +++ b/Source/Scene/Appearance.js @@ -63,6 +63,10 @@ define([ enabled : true, face : CullFace.BACK }, + depthTest : { + enabled : true + }, + depthMask : false, blending : BlendingState.ALPHA_BLEND } })); diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index 7101bac4d5c9..fa81af2a8809 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -2,35 +2,45 @@ define([ '../Core/destroyObject', '../Core/Matrix4', + '../Core/Color', '../Core/GeometryFilters', '../Core/PrimitiveType', '../Core/BoundingSphere', + '../Core/Geometry', + '../Core/GeometryAttribute', + '../Core/ComponentDatatype', '../Renderer/BufferUsage', '../Renderer/VertexLayout', '../Renderer/CommandLists', '../Renderer/DrawCommand', + '../Renderer/createPickFragmentShaderSource', './SceneMode' ], function( destroyObject, Matrix4, + Color, GeometryFilters, PrimitiveType, BoundingSphere, + Geometry, + GeometryAttribute, + ComponentDatatype, BufferUsage, VertexLayout, CommandLists, DrawCommand, + createPickFragmentShaderSource, SceneMode) { "use strict"; /** * DOC_TBA */ - var Primitive = function(meshes, appearance) { + var Primitive = function(geometries, appearance) { /** * DOC_TBA */ - this.meshes = meshes; + this.geometries = geometries; /** * DOC_TBA @@ -49,18 +59,71 @@ define([ this._sp = undefined; this._rs = undefined; - this._va = undefined; + this._va = []; + + this._pickSP = undefined; + this._pickIds = []; this._commandLists = new CommandLists(); }; - function processGeometry(geometries) { + function addPickColorAttribute(primitive, context) { + var geometries = primitive.geometries; + var length = geometries.length; + var i; + + for (i = 0; i < length; ++i) { + var geometry = geometries[i]; + var attributes = geometry.attributes; + var positionAttr = attributes.position; + var numberOfComponents = 4 * (positionAttr.values.length / positionAttr.componentsPerAttribute); + + attributes.pickData = new GeometryAttribute({ + componentDatatype : ComponentDatatype.UNSIGNED_BYTE, + componentsPerAttribute : 4, + normalize : true, + values : new Uint8Array(numberOfComponents) + }); + + if (typeof geometry.pickData !== 'undefined') { + var pickId = context.createPickId({ + primitive : primitive, + pickData : geometry.pickData + }); + primitive._pickIds.push(pickId); + + var pickColor = pickId.color; + var red = Color.floatToByte(pickColor.red); + var green = Color.floatToByte(pickColor.green); + var blue = Color.floatToByte(pickColor.blue); + var alpha = Color.floatToByte(pickColor.alpha); + var values = attributes.pickData.values; + + for (var j = 0; j < numberOfComponents; j += 4) { + values[j] = red; + values[j + 1] = green; + values[j + 2] = blue; + values[j + 3] = alpha; + } + } + } + } + + function processGeometry(primitive, context) { // Unify to world coordinates before combining. + var geometries = primitive.geometries; var length = geometries.length; for (var i = 0; i < length; ++i) { GeometryFilters.transformToWorldCoordinates(geometries[i]); } + // Add pickColor attribute if any geometries are pickable + var pickable = Geometry.isPickable(geometries); + if (pickable) { + addPickColorAttribute(primitive, context); + } + + // Combine into single geometry for better rendering performance. var geometry = GeometryFilters.combine(geometries); return geometry; @@ -75,22 +138,26 @@ define([ return; } -// TODO: throw if meshes and appearance are not defined +// TODO: throw if geometries and appearance are not defined var colorCommands = this._commandLists.colorList; + var pickCommands = this._commandLists.pickList; + var length; + var i; - if (typeof this._va === 'undefined') { - var mesh = processGeometry(this.meshes); - // Break into multiple meshes to fit within unsigned short indices if needed - var meshes = GeometryFilters.fitToUnsignedShortIndices(mesh); - var attributeIndices = GeometryFilters.createAttributeIndices(mesh); + if (typeof this._sp === 'undefined') { + var pickable = Geometry.isPickable(this.geometries); + + var geometry = processGeometry(this, context); + // Break into multiple geometries to fit within unsigned short indices if needed + var geometries = GeometryFilters.fitToUnsignedShortIndices(geometry); + var attributeIndices = GeometryFilters.createAttributeIndices(geometry); var va = []; - var length = meshes.length; - var i; + length = geometries.length; for (i = 0; i < length; ++i) { va.push(context.createVertexArrayFromMesh({ - mesh : meshes[i], + mesh : geometries[i], attributeIndices : attributeIndices, bufferUsage : BufferUsage.STATIC_DRAW, vertexLayout : VertexLayout.INTERLEAVED @@ -98,31 +165,54 @@ define([ } var appearance = this.appearance; + var vs = appearance.vertexShaderSource; + var fs = appearance.getFragmentShaderSource(); this._va = va; - this._sp = context.getShaderCache().replaceShaderProgram(this._sp, appearance.vertexShaderSource, appearance.getFragmentShaderSource(), attributeIndices); +// TODO: recompile on material change. + this._sp = context.getShaderCache().replaceShaderProgram(this._sp, appearance.vertexShaderSource, fs, attributeIndices); + if (pickable) { + this._pickSP = context.getShaderCache().replaceShaderProgram(this._pickSP, vs, createPickFragmentShaderSource(fs, 'varying'), attributeIndices); + } this._rs = context.createRenderState(appearance.renderState); for (i = 0; i < length; ++i) { var command = new DrawCommand(); -// TODO: this assumes indices in the meshes - and only one set - command.primitiveType = mesh.indexLists[0].primitiveType; +// TODO: this assumes indices in the geometries - and only one set + command.primitiveType = geometry.indexLists[0].primitiveType; command.vertexArray = this._va[i]; command.renderState = this._rs; command.shaderProgram = this._sp; command.uniformMap = appearance.material._uniforms; -// TODO: could use bounding volume per mesh - command.boundingVolume = mesh.boundingSphere; +// TODO: could use bounding volume per geometry + command.boundingVolume = geometry.boundingSphere; colorCommands.push(command); + + if (pickable) { + var pickCommand = new DrawCommand(); + pickCommand.primitiveType = geometry.indexLists[0].primitiveType; + pickCommand.vertexArray = this._va[i]; + pickCommand.renderState = this._rs; + pickCommand.shaderProgram = this._pickSP; + pickCommand.uniformMap = appearance.material._uniforms; + pickCommand.boundingVolume = geometry.boundingSphere; + pickCommands.push(pickCommand); + } } } - if (frameState.passes.color) { - // The geometry is static but the model matrix can change - var len = colorCommands.length; - for (var i = 0; i < len; ++i) { + // The geometry is static but the model matrix can change + if (frameState.passes.color || frameState.passes.pick) { + length = colorCommands.length; + for (var i = 0; i < length; ++i) { colorCommands[i].modelMatrix = this.modelMatrix; } + + length = pickCommands.length; + for (var i = 0; i < length; ++i) { + pickCommands[i].modelMatrix = this.modelMatrix; + } + commandList.push(this._commandLists); } }; @@ -138,16 +228,25 @@ define([ * DOC_TBA */ Primitive.prototype.destroy = function() { + var length; + var i; + this._sp = this._sp && this._sp.release(); + this._pickSP = this._pickSP && this._pickSP.release(); var va = this._va; - if (typeof va !== 'undefined') { - var length = va.length; - for (var i = 0; i < length; ++i) { - va[i].destroy(); - } - this._va = undefined; + length = va.length; + for (i = 0; i < length; ++i) { + va[i].destroy(); + } + this._va = undefined; + + var pickIds = this_pickIds; + length = pickIds.length; + for (i = 0; i < length; ++i) { + pickIds[i].destroy(); } + this.this_pickIds = undefined; return destroyObject(this); }; diff --git a/Source/Shaders/DefaultAppearanceFS.glsl b/Source/Shaders/DefaultAppearanceFS.glsl index 346f8e3334b3..6394377c2c70 100644 --- a/Source/Shaders/DefaultAppearanceFS.glsl +++ b/Source/Shaders/DefaultAppearanceFS.glsl @@ -1,15 +1,15 @@ -varying vec3 v_normalEC; -varying vec3 v_positionEC; -varying vec2 v_st; +//varying vec3 v_normalEC; +//varying vec3 v_positionEC; +//varying vec2 v_st; void main() { - vec3 positionToEyeEC = -v_positionEC; +// vec3 positionToEyeEC = -v_positionEC; czm_materialInput materialInput; - materialInput.normalEC = v_normalEC; - materialInput.positionToEyeEC = positionToEyeEC; - materialInput.st = v_st; +// materialInput.normalEC = v_normalEC; +// materialInput.positionToEyeEC = positionToEyeEC; +// materialInput.st = v_st; czm_material material = czm_getMaterial(materialInput); // gl_FragColor = czm_phong(normalize(positionToEyeEC), material); diff --git a/Source/Shaders/DefaultAppearanceVS.glsl b/Source/Shaders/DefaultAppearanceVS.glsl index 6c3501e57e0c..617d873f4824 100644 --- a/Source/Shaders/DefaultAppearanceVS.glsl +++ b/Source/Shaders/DefaultAppearanceVS.glsl @@ -1,16 +1,19 @@ attribute vec4 position; -attribute vec3 normal; -attribute vec2 st; +//attribute vec3 normal; +//attribute vec2 st; +attribute vec4 pickColor; -varying vec3 v_normalEC; -varying vec3 v_positionEC; -varying vec2 v_st; +//varying vec3 v_normalEC; +//varying vec3 v_positionEC; +//varying vec2 v_st; +varying vec4 czm_pickColor; void main() { - v_normalEC = czm_normal * normal; // normal in eye coordinates - v_positionEC = (czm_modelView * position).xyz; // position in eye coordinates - v_st = st; +// v_normalEC = czm_normal * normal; // normal in eye coordinates +// v_positionEC = (czm_modelView * position).xyz; // position in eye coordinates +// v_st = st; + czm_pickColor = pickColor; gl_Position = czm_modelViewProjection * position; } From 45113ade87d95f3c3509808470d8c2518d7e3dab Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Fri, 10 May 2013 17:27:03 -0400 Subject: [PATCH 020/306] Added GPU RTE to generic primitive --- Source/Scene/Primitive.js | 17 ++++++++++------- Source/Shaders/DefaultAppearanceVS.glsl | 11 +++++++---- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index fa81af2a8809..ffea54800a48 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -110,22 +110,25 @@ define([ } function processGeometry(primitive, context) { - // Unify to world coordinates before combining. var geometries = primitive.geometries; - var length = geometries.length; - for (var i = 0; i < length; ++i) { - GeometryFilters.transformToWorldCoordinates(geometries[i]); - } // Add pickColor attribute if any geometries are pickable - var pickable = Geometry.isPickable(geometries); - if (pickable) { + if (Geometry.isPickable(geometries)) { addPickColorAttribute(primitive, context); } + // Unify to world coordinates before combining. + var length = geometries.length; + for (var i = 0; i < length; ++i) { + GeometryFilters.transformToWorldCoordinates(geometries[i]); + } + // Combine into single geometry for better rendering performance. var geometry = GeometryFilters.combine(geometries); + // Split position for GPU RTE + geometry = GeometryFilters.encodeAttribute(geometry, 'position', 'positionHigh', 'positionLow'); + return geometry; } diff --git a/Source/Shaders/DefaultAppearanceVS.glsl b/Source/Shaders/DefaultAppearanceVS.glsl index 617d873f4824..5b6d6672bcd9 100644 --- a/Source/Shaders/DefaultAppearanceVS.glsl +++ b/Source/Shaders/DefaultAppearanceVS.glsl @@ -1,4 +1,5 @@ -attribute vec4 position; +attribute vec3 positionHigh; +attribute vec3 positionLow; //attribute vec3 normal; //attribute vec2 st; attribute vec4 pickColor; @@ -10,10 +11,12 @@ varying vec4 czm_pickColor; void main() { -// v_normalEC = czm_normal * normal; // normal in eye coordinates -// v_positionEC = (czm_modelView * position).xyz; // position in eye coordinates + vec4 p = vec4(czm_translateRelativeToEye(positionHigh, positionLow), 1.0); + +// v_normalEC = czm_normal * normal; // normal in eye coordinates +// v_positionEC = (czm_modelViewRelativeToEye * p).xyz; // position in eye coordinates // v_st = st; czm_pickColor = pickColor; - gl_Position = czm_modelViewProjection * position; + gl_Position = czm_modelViewProjectionRelativeToEye * p; } From 5a4a01567df4e62ef47ad672e38bebffc2d39718 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Fri, 10 May 2013 17:36:15 -0400 Subject: [PATCH 021/306] Cleaned up GLSL functions --- Apps/Sandcastle/gallery/Custom Rendering.html | 4 ++-- Source/Renderer/ShaderProgram.js | 8 ++++---- Source/Shaders/BillboardCollectionVS.glsl | 2 +- Source/Shaders/BuiltinFunctions.glsl | 12 ++++++------ Source/Shaders/CentralBodyVS.glsl | 4 ++-- Source/Shaders/DefaultAppearanceVS.glsl | 2 +- Source/Shaders/PolygonVS.glsl | 4 ++-- Source/Shaders/PolylineVS.glsl | 12 ++++++------ Specs/Core/BoxGeometrySpec.js | 5 ++++- Specs/Renderer/BuiltinFunctionsSpec.js | 4 ++-- 10 files changed, 30 insertions(+), 27 deletions(-) diff --git a/Apps/Sandcastle/gallery/Custom Rendering.html b/Apps/Sandcastle/gallery/Custom Rendering.html index cb54420aa338..d25008d3b030 100644 --- a/Apps/Sandcastle/gallery/Custom Rendering.html +++ b/Apps/Sandcastle/gallery/Custom Rendering.html @@ -270,8 +270,8 @@ if (typeof colorCommand.shaderProgram === 'undefined') { var vs = ''; - vs += 'attribute vec3 position2D;'; - vs += 'attribute vec3 position3D;'; + vs += 'attribute vec4 position2D;'; + vs += 'attribute vec4 position3D;'; vs += 'void main()'; vs += '{'; vs += ' vec4 p = czm_columbusViewMorph(position2D, position3D, czm_morphTime);'; diff --git a/Source/Renderer/ShaderProgram.js b/Source/Renderer/ShaderProgram.js index f0aaf2da8fd9..9665bae2a2ee 100644 --- a/Source/Renderer/ShaderProgram.js +++ b/Source/Renderer/ShaderProgram.js @@ -759,8 +759,8 @@ define([ * * void main() * { - * vec3 p = czm_translateRelativeToEye(positionHigh, positionLow); - * gl_Position = czm_projection * (czm_modelViewRelativeToEye * vec4(p, 1.0)); + * vec4 p = czm_translateRelativeToEye(positionHigh, positionLow); + * gl_Position = czm_projection * (czm_modelViewRelativeToEye * p); * } * * @see czm_modelViewProjectionRelativeToEye @@ -963,8 +963,8 @@ define([ * * void main() * { - * vec3 p = czm_translateRelativeToEye(positionHigh, positionLow); - * gl_Position = czm_modelViewProjectionRelativeToEye * vec4(p, 1.0); + * vec4 p = czm_translateRelativeToEye(positionHigh, positionLow); + * gl_Position = czm_modelViewProjectionRelativeToEye * p; * } * * @see czm_modelViewRelativeToEye diff --git a/Source/Shaders/BillboardCollectionVS.glsl b/Source/Shaders/BillboardCollectionVS.glsl index 9f18b56f7fcc..9f26e1056cbf 100644 --- a/Source/Shaders/BillboardCollectionVS.glsl +++ b/Source/Shaders/BillboardCollectionVS.glsl @@ -38,7 +38,7 @@ void main() /////////////////////////////////////////////////////////////////////////// - vec4 p = vec4(czm_translateRelativeToEye(positionHigh, positionLow), 1.0); + vec4 p = czm_translateRelativeToEye(positionHigh, positionLow); vec4 positionEC = czm_modelViewRelativeToEye * p; positionEC = czm_eyeOffset(positionEC, eyeOffset); positionEC.xyz *= show; diff --git a/Source/Shaders/BuiltinFunctions.glsl b/Source/Shaders/BuiltinFunctions.glsl index 174272943917..6ee51d81ca55 100644 --- a/Source/Shaders/BuiltinFunctions.glsl +++ b/Source/Shaders/BuiltinFunctions.glsl @@ -670,10 +670,10 @@ const int czm_morphing = 3; * @name czm_columbusViewMorph * @glslFunction */ -vec4 czm_columbusViewMorph(vec3 position2D, vec3 position3D, float time) +vec4 czm_columbusViewMorph(vec4 position2D, vec4 position3D, float time) { // Just linear for now. - vec3 p = mix(position2D, position3D, time); + vec3 p = mix(position2D.xyz, position3D.xyz, time); return vec4(p, 1.0); } @@ -984,20 +984,20 @@ float czm_latitudeToWebMercatorFraction(float latitude, float southMercatorYLow, * * void main() * { - * vec3 p = czm_translateRelativeToEye(positionHigh, positionLow); - * gl_Position = czm_modelViewProjectionRelativeToEye * vec4(p, 1.0); + * vec4 p = czm_translateRelativeToEye(positionHigh, positionLow); + * gl_Position = czm_modelViewProjectionRelativeToEye * p; * } * * @see czm_modelViewRelativeToEye * @see czm_modelViewProjectionRelativeToEye * @see EncodedCartesian3 */ -vec3 czm_translateRelativeToEye(vec3 high, vec3 low) +vec4 czm_translateRelativeToEye(vec3 high, vec3 low) { vec3 highDifference = high - czm_encodedCameraPositionMCHigh; vec3 lowDifference = low - czm_encodedCameraPositionMCLow; - return highDifference + lowDifference; + return vec4(highDifference + lowDifference, 1.0); } /** diff --git a/Source/Shaders/CentralBodyVS.glsl b/Source/Shaders/CentralBodyVS.glsl index 827b398f5e8d..7637e986a3d6 100644 --- a/Source/Shaders/CentralBodyVS.glsl +++ b/Source/Shaders/CentralBodyVS.glsl @@ -74,8 +74,8 @@ vec4 getPositionMorphingMode(vec3 position3DWC) // We do not do RTC while morphing, so there is potential for jitter. // This is unlikely to be noticable, though. float yPositionFraction = get2DYPositionFraction(); - vec3 position2DWC = vec3(0.0, mix(u_tileExtent.st, u_tileExtent.pq, vec2(textureCoordinates.x, yPositionFraction))); - vec4 morphPosition = czm_columbusViewMorph(position2DWC, position3DWC, czm_morphTime); + vec4 position2DWC = vec4(0.0, mix(u_tileExtent.st, u_tileExtent.pq, vec2(textureCoordinates.x, yPositionFraction)), 1.0); + vec4 morphPosition = czm_columbusViewMorph(position2DWC, vec4(position3DWC, 1.0), czm_morphTime); return czm_modelViewProjection * morphPosition; } diff --git a/Source/Shaders/DefaultAppearanceVS.glsl b/Source/Shaders/DefaultAppearanceVS.glsl index 5b6d6672bcd9..d6c63f58e08f 100644 --- a/Source/Shaders/DefaultAppearanceVS.glsl +++ b/Source/Shaders/DefaultAppearanceVS.glsl @@ -11,7 +11,7 @@ varying vec4 czm_pickColor; void main() { - vec4 p = vec4(czm_translateRelativeToEye(positionHigh, positionLow), 1.0); + vec4 p = czm_translateRelativeToEye(positionHigh, positionLow); // v_normalEC = czm_normal * normal; // normal in eye coordinates // v_positionEC = (czm_modelViewRelativeToEye * p).xyz; // position in eye coordinates diff --git a/Source/Shaders/PolygonVS.glsl b/Source/Shaders/PolygonVS.glsl index abf9c436555f..04bd016878d6 100644 --- a/Source/Shaders/PolygonVS.glsl +++ b/Source/Shaders/PolygonVS.glsl @@ -16,11 +16,11 @@ void main() if (czm_morphTime == 1.0) { - p = vec4(czm_translateRelativeToEye(position3DHigh, position3DLow), 1.0); + p = czm_translateRelativeToEye(position3DHigh, position3DLow); } else if (czm_morphTime == 0.0) { - p = vec4(czm_translateRelativeToEye(vec3(u_height, position2DHigh), vec3(u_height, position2DLow)), 1.0); + p = czm_translateRelativeToEye(vec3(u_height, position2DHigh), vec3(u_height, position2DLow)); } else { diff --git a/Source/Shaders/PolylineVS.glsl b/Source/Shaders/PolylineVS.glsl index 9e18ac4de13c..3e262cb041d0 100644 --- a/Source/Shaders/PolylineVS.glsl +++ b/Source/Shaders/PolylineVS.glsl @@ -68,15 +68,15 @@ void main() vec4 p, prev, next; if (czm_morphTime == 1.0) { - p = vec4(czm_translateRelativeToEye(position3DHigh.xyz, position3DLow.xyz), 1.0); - prev = vec4(czm_translateRelativeToEye(prevPosition3DHigh.xyz, prevPosition3DLow.xyz), 1.0); - next = vec4(czm_translateRelativeToEye(nextPosition3DHigh.xyz, nextPosition3DLow.xyz), 1.0); + p = czm_translateRelativeToEye(position3DHigh.xyz, position3DLow.xyz); + prev = czm_translateRelativeToEye(prevPosition3DHigh.xyz, prevPosition3DLow.xyz); + next = czm_translateRelativeToEye(nextPosition3DHigh.xyz, nextPosition3DLow.xyz); } else if (czm_morphTime == 0.0) { - p = vec4(czm_translateRelativeToEye(position2DHigh.zxy, position2DLow.zxy), 1.0); - prev = vec4(czm_translateRelativeToEye(prevPosition2DHigh.zxy, prevPosition2DLow.zxy), 1.0); - next = vec4(czm_translateRelativeToEye(nextPosition2DHigh.zxy, nextPosition2DLow.zxy), 1.0); + p = czm_translateRelativeToEye(position2DHigh.zxy, position2DLow.zxy); + prev = czm_translateRelativeToEye(prevPosition2DHigh.zxy, prevPosition2DLow.zxy); + next = czm_translateRelativeToEye(nextPosition2DHigh.zxy, nextPosition2DLow.zxy); } else { diff --git a/Specs/Core/BoxGeometrySpec.js b/Specs/Core/BoxGeometrySpec.js index ff232e2a0050..7605e6c69233 100644 --- a/Specs/Core/BoxGeometrySpec.js +++ b/Specs/Core/BoxGeometrySpec.js @@ -1,9 +1,11 @@ /*global defineSuite*/ defineSuite([ 'Core/BoxGeometry', + 'Core/VertexFormat', 'Core/Cartesian3' ], function( BoxGeometry, + VertexFormat, Cartesian3) { "use strict"; /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/ @@ -18,7 +20,8 @@ defineSuite([ it('compute1', function() { var m = new BoxGeometry({ - dimensions : new Cartesian3(1, 2, 3) + dimensions : new Cartesian3(1, 2, 3), + vertexFormat : VertexFormat.POSITION_ONLY }); expect(m.attributes.position.values.length).toEqual(8 * 3); diff --git a/Specs/Renderer/BuiltinFunctionsSpec.js b/Specs/Renderer/BuiltinFunctionsSpec.js index 2afcde525ce5..59deef109879 100644 --- a/Specs/Renderer/BuiltinFunctionsSpec.js +++ b/Specs/Renderer/BuiltinFunctionsSpec.js @@ -173,8 +173,8 @@ defineSuite([ 'uniform vec3 u_high;' + 'uniform vec3 u_low;' + 'void main() { ' + - ' vec3 p = czm_translateRelativeToEye(u_high, u_low);' + - ' gl_FragColor = vec4(p == vec3(5.0, 3.0, 1.0)); ' + + ' vec4 p = czm_translateRelativeToEye(u_high, u_low);' + + ' gl_FragColor = vec4(p == vec4(5.0, 3.0, 1.0, 1.0)); ' + '}'; verifyDraw(fs, uniformMap); From 730b53900fdff729be0e46a851d438f49cf992c8 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Mon, 13 May 2013 09:41:34 -0400 Subject: [PATCH 022/306] Minor improvements --- Source/Core/GeometryFilters.js | 5 ++++- Source/Renderer/ShaderProgram.js | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Source/Core/GeometryFilters.js b/Source/Core/GeometryFilters.js index 8fc03fd48550..5489c77c3f5c 100644 --- a/Source/Core/GeometryFilters.js +++ b/Source/Core/GeometryFilters.js @@ -378,7 +378,10 @@ define([ indexLists : [new GeometryIndices({ primitiveType : primitiveType, values : indices - })] + })], + boundingSphere : (typeof mesh.boundingSphere !== 'undefined') ? BoundingSphere.clone(mesh.boundingSphere) : undefined, + modelMatrix : (typeof mesh.modelMatrix !== 'undefined') ? Matrix4.clone(mesh.modelMatrix) : undefined, + pickData : mesh.pickData }); } diff --git a/Source/Renderer/ShaderProgram.js b/Source/Renderer/ShaderProgram.js index 9665bae2a2ee..60f378ad9296 100644 --- a/Source/Renderer/ShaderProgram.js +++ b/Source/Renderer/ShaderProgram.js @@ -2516,7 +2516,7 @@ define([ gl.deleteShader(vertexShader); gl.deleteShader(fragmentShader); - if (attributeLocations) { + if (typeof attributeLocations !== 'undefined') { for ( var attribute in attributeLocations) { if (attributeLocations.hasOwnProperty(attribute)) { gl.bindAttribLocation(program, attributeLocations[attribute], attribute); From 9925221098c1407faccb4740347cf60af92f5a23 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Mon, 13 May 2013 09:55:10 -0400 Subject: [PATCH 023/306] Fix pickColor/pickData attribute mismatch --- Apps/CesiumViewer/CesiumViewer.js | 15 +++++++++++---- Source/Scene/Primitive.js | 4 ++-- Source/Shaders/DefaultAppearanceFS.glsl | 14 +++++++------- Source/Shaders/DefaultAppearanceVS.glsl | 16 ++++++++-------- 4 files changed, 28 insertions(+), 21 deletions(-) diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index dce4a09cc6fb..03a58d444494 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -97,9 +97,10 @@ define([ pickData : 'mesh3' }); +// var primitive = new Primitive([mesh3], Appearance.CLOSED_TRANSLUCENT); var primitive = new Primitive([mesh, mesh2, mesh3], Appearance.CLOSED_TRANSLUCENT); + widget.scene.getPrimitives().add(primitive); -/* var m = new Material({ context : widget.scene.getContext(), fabric : { @@ -118,10 +119,16 @@ define([ material : m, renderState : rs }); - var primitive = new Primitive(mesh3, appearance); -*/ - widget.scene.getPrimitives().add(primitive); + var mesh4 = new BoxGeometry({ + dimensions : new Cartesian3(1000000.0, 1000000.0, 1000000.0), + modelMatrix : Matrix4.multiplyByTranslation(Transforms.eastNorthUpToFixedFrame( + Ellipsoid.WGS84.cartographicToCartesian(Cartographic.fromDegrees(-75.59777, 40.03883))), new Cartesian3(0.0, 0.0, 4500000.0)), + pickData : 'mesh4' + }); + + var primitive2 = new Primitive([mesh4], appearance); + widget.scene.getPrimitives().add(primitive2); var handler = new ScreenSpaceEventHandler(scene.getCanvas()); diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index ffea54800a48..3fc971accbf2 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -78,7 +78,7 @@ define([ var positionAttr = attributes.position; var numberOfComponents = 4 * (positionAttr.values.length / positionAttr.componentsPerAttribute); - attributes.pickData = new GeometryAttribute({ + attributes.pickColor = new GeometryAttribute({ componentDatatype : ComponentDatatype.UNSIGNED_BYTE, componentsPerAttribute : 4, normalize : true, @@ -97,7 +97,7 @@ define([ var green = Color.floatToByte(pickColor.green); var blue = Color.floatToByte(pickColor.blue); var alpha = Color.floatToByte(pickColor.alpha); - var values = attributes.pickData.values; + var values = attributes.pickColor.values; for (var j = 0; j < numberOfComponents; j += 4) { values[j] = red; diff --git a/Source/Shaders/DefaultAppearanceFS.glsl b/Source/Shaders/DefaultAppearanceFS.glsl index 6394377c2c70..346f8e3334b3 100644 --- a/Source/Shaders/DefaultAppearanceFS.glsl +++ b/Source/Shaders/DefaultAppearanceFS.glsl @@ -1,15 +1,15 @@ -//varying vec3 v_normalEC; -//varying vec3 v_positionEC; -//varying vec2 v_st; +varying vec3 v_normalEC; +varying vec3 v_positionEC; +varying vec2 v_st; void main() { -// vec3 positionToEyeEC = -v_positionEC; + vec3 positionToEyeEC = -v_positionEC; czm_materialInput materialInput; -// materialInput.normalEC = v_normalEC; -// materialInput.positionToEyeEC = positionToEyeEC; -// materialInput.st = v_st; + materialInput.normalEC = v_normalEC; + materialInput.positionToEyeEC = positionToEyeEC; + materialInput.st = v_st; czm_material material = czm_getMaterial(materialInput); // gl_FragColor = czm_phong(normalize(positionToEyeEC), material); diff --git a/Source/Shaders/DefaultAppearanceVS.glsl b/Source/Shaders/DefaultAppearanceVS.glsl index d6c63f58e08f..0a851ed9fa4f 100644 --- a/Source/Shaders/DefaultAppearanceVS.glsl +++ b/Source/Shaders/DefaultAppearanceVS.glsl @@ -1,21 +1,21 @@ attribute vec3 positionHigh; attribute vec3 positionLow; -//attribute vec3 normal; -//attribute vec2 st; +attribute vec3 normal; +attribute vec2 st; attribute vec4 pickColor; -//varying vec3 v_normalEC; -//varying vec3 v_positionEC; -//varying vec2 v_st; +varying vec3 v_normalEC; +varying vec3 v_positionEC; +varying vec2 v_st; varying vec4 czm_pickColor; void main() { vec4 p = czm_translateRelativeToEye(positionHigh, positionLow); -// v_normalEC = czm_normal * normal; // normal in eye coordinates -// v_positionEC = (czm_modelViewRelativeToEye * p).xyz; // position in eye coordinates -// v_st = st; + v_normalEC = czm_normal * normal; // normal in eye coordinates + v_positionEC = (czm_modelViewRelativeToEye * p).xyz; // position in eye coordinates + v_st = st; czm_pickColor = pickColor; gl_Position = czm_modelViewProjectionRelativeToEye * p; From eed94382fe2b4adef3d09ad9f1d463f3cbfb2eff Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Mon, 13 May 2013 11:03:36 -0400 Subject: [PATCH 024/306] Remove unused PlaneTessellator --- Apps/CesiumViewer/CesiumViewer.js | 2 +- CHANGES.md | 1 + Source/Core/PlaneTessellator.js | 73 ------------------------------ Source/Scene/Primitive.js | 28 ++++++------ Specs/Core/PlaneTessellatorSpec.js | 63 -------------------------- 5 files changed, 15 insertions(+), 152 deletions(-) delete mode 100644 Source/Core/PlaneTessellator.js delete mode 100644 Specs/Core/PlaneTessellatorSpec.js diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index 03a58d444494..db73b658b212 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -127,7 +127,7 @@ define([ pickData : 'mesh4' }); - var primitive2 = new Primitive([mesh4], appearance); + var primitive2 = new Primitive(mesh4, appearance); widget.scene.getPrimitives().add(primitive2); diff --git a/CHANGES.md b/CHANGES.md index 177bb73113ce..823b9e3b574c 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -10,6 +10,7 @@ Beta Releases * Replaced tessellators and meshes with geometry. In particular: * Replaced `CubeMapEllipsoidTessellator` with `EllipsoidGeometry`. * Replaced `BoxTessellator` with `BoxGeometry`. + * Removed `PlaneTessellator`. It was incomplete and not used. * Renamed `MeshFilters` to `GeometryFilters`. * Renamed `MeshFilters.toWireframeInPlace` to `GeometryFilters.toWireframe`. * Renamed `ComponentDatatype.*.toTypedArray` to `ComponentDatatype.*.createTypedArray`. diff --git a/Source/Core/PlaneTessellator.js b/Source/Core/PlaneTessellator.js deleted file mode 100644 index 23443d36320d..000000000000 --- a/Source/Core/PlaneTessellator.js +++ /dev/null @@ -1,73 +0,0 @@ -/*global define*/ -define([ - './DeveloperError', - './Cartesian2', - './PrimitiveType', - './defaultValue' - ], function( - DeveloperError, - Cartesian2, - PrimitiveType, - defaultValue) { - "use strict"; - - /** - * DOC_TBA - * - * @exports PlaneTessellator - */ - var PlaneTessellator = { - /** - * DOC_TBA - * - * @exception {DeveloperError} Resolution must be greater than one in both the x and y directions. - */ - compute : function(options) { - options = defaultValue(options, defaultValue.EMPTY_OBJECT); - var resolution = typeof options.resolution !== "undefined" ? options.resolution : new Cartesian2(2, 2); - var onInterpolation = options.onInterpolation; // Can be undefined - - if (resolution.x <= 1 || resolution.y <= 1) { - throw new DeveloperError('Resolution must be greater than one in both the x and y directions.'); - } - - var i; - var j; - - // To allow computing custom attributes, e.g., texture coordinates, etc. - if (onInterpolation) { - for (j = 0; j < resolution.y; ++j) { - var yTime = j / (resolution.y - 1); - - for (i = 0; i < resolution.x; ++i) { - var xTime = i / (resolution.x - 1); - onInterpolation(new Cartesian2(xTime, yTime)); - } - } - } - - var indices = []; - - // Counterclockwise winding order - for (j = 0; j < resolution.y - 1; ++j) { - var row = j * resolution.x; - var aboveRow = (j + 1) * resolution.x; - - for (i = 0; i < resolution.x - 1; ++i) { - indices.push(row + i, row + i + 1, aboveRow + i + 1); - indices.push(row + i, aboveRow + i + 1, aboveRow + i); - } - } - - return { - attributes : {}, - indexLists : [{ - primitiveType : PrimitiveType.TRIANGLES, - values : indices - }] - }; - } - }; - - return PlaneTessellator; -}); \ No newline at end of file diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index 3fc971accbf2..c80525df6fe3 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -67,8 +67,7 @@ define([ this._commandLists = new CommandLists(); }; - function addPickColorAttribute(primitive, context) { - var geometries = primitive.geometries; + function addPickColorAttribute(primitive, geometries, context) { var length = geometries.length; var i; @@ -109,12 +108,10 @@ define([ } } - function processGeometry(primitive, context) { - var geometries = primitive.geometries; - + function processGeometry(primitive, geometries, context) { // Add pickColor attribute if any geometries are pickable if (Geometry.isPickable(geometries)) { - addPickColorAttribute(primitive, context); + addPickColorAttribute(primitive, geometries, context); } // Unify to world coordinates before combining. @@ -136,31 +133,31 @@ define([ * @private */ Primitive.prototype.update = function(context, frameState, commandList) { - if (!this.show || (frameState.mode !== SceneMode.SCENE3D)) { + if (!this.show || + (frameState.mode !== SceneMode.SCENE3D) || + (typeof this.geometries === 'undefined') || + (typeof this.appearance === 'undefined')) { // TODO: support Columbus view and 2D return; } -// TODO: throw if geometries and appearance are not defined - var colorCommands = this._commandLists.colorList; var pickCommands = this._commandLists.pickList; var length; var i; if (typeof this._sp === 'undefined') { - var pickable = Geometry.isPickable(this.geometries); - - var geometry = processGeometry(this, context); + var geometries = (this.geometries instanceof Array) ? this.geometries : [this.geometries]; + var geometry = processGeometry(this, geometries, context); // Break into multiple geometries to fit within unsigned short indices if needed - var geometries = GeometryFilters.fitToUnsignedShortIndices(geometry); + var finalGeometries = GeometryFilters.fitToUnsignedShortIndices(geometry); var attributeIndices = GeometryFilters.createAttributeIndices(geometry); var va = []; - length = geometries.length; + length = finalGeometries.length; for (i = 0; i < length; ++i) { va.push(context.createVertexArrayFromMesh({ - mesh : geometries[i], + mesh : finalGeometries[i], attributeIndices : attributeIndices, bufferUsage : BufferUsage.STATIC_DRAW, vertexLayout : VertexLayout.INTERLEAVED @@ -170,6 +167,7 @@ define([ var appearance = this.appearance; var vs = appearance.vertexShaderSource; var fs = appearance.getFragmentShaderSource(); + var pickable = Geometry.isPickable(geometries); this._va = va; // TODO: recompile on material change. diff --git a/Specs/Core/PlaneTessellatorSpec.js b/Specs/Core/PlaneTessellatorSpec.js deleted file mode 100644 index 695f66df824f..000000000000 --- a/Specs/Core/PlaneTessellatorSpec.js +++ /dev/null @@ -1,63 +0,0 @@ -/*global defineSuite*/ -defineSuite(['Core/PlaneTessellator'], function(PlaneTessellator) { - "use strict"; - /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/ - - it('compute with default arguments', function() { - var m = PlaneTessellator.compute(); - - expect(m.indexLists[0].values.length).toEqual(2 * 3); // 2 triangles - }); - - it('compute with arguments', function() { - var m = PlaneTessellator.compute({ - resolution : { - x : 4, - y : 3 - }, - onInterpolation : function(time) { - } - }); - - expect(m.indexLists[0].values.length).toEqual(12 * 3); // 8 triangles - }); - - it('compute with onInterpolation callback', function() { - var callbacks = []; - - PlaneTessellator.compute({ - resolution : { - x : 2, - y : 2 - }, - onInterpolation : function(time) { - callbacks.push(time); - } - }); - - expect(callbacks).toEqual([{ - x : 0.0, - y : 0.0 - }, { - x : 1.0, - y : 0.0 - }, { - x : 0.0, - y : 1.0 - }, { - x : 1.0, - y : 1.0 - }]); - }); - - it('throws if resolution is less than 1', function() { - expect(function() { - PlaneTessellator.compute({ - resolution: { - x : 0.0, - y : 0.0 - } - }); - }).toThrow(); - }); -}); \ No newline at end of file From fa4ab616adb3ce5b4f4733792059801580da78a1 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Mon, 13 May 2013 17:45:17 -0400 Subject: [PATCH 025/306] Move some private functions --- Source/Core/GeometryFilters.js | 88 +++++++++++++++++----------------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/Source/Core/GeometryFilters.js b/Source/Core/GeometryFilters.js index 5489c77c3f5c..6ce1ff5d4fc3 100644 --- a/Source/Core/GeometryFilters.js +++ b/Source/Core/GeometryFilters.js @@ -580,50 +580,6 @@ define([ return mesh; }; - function findAttributesInAllMeshes(meshes) { - var length = meshes.length; - - var attributesInAllMeshes = {}; - - var attributes0 = meshes[0].attributes; - var name; - - for (name in attributes0) { - if (attributes0.hasOwnProperty(name)) { - var attribute = attributes0[name]; - var numberOfComponents = attribute.values.length; - var inAllMeshes = true; - - // Does this same attribute exist in all meshes? - for (var i = 1; i < length; ++i) { - var otherAttribute = meshes[i].attributes[name]; - - if ((typeof otherAttribute === 'undefined') || - (attribute.componentDatatype !== otherAttribute.componentDatatype) || - (attribute.componentsPerAttribute !== otherAttribute.componentsPerAttribute) || - (attribute.normalize !== otherAttribute.normalize)) { - - inAllMeshes = false; - break; - } - - numberOfComponents += otherAttribute.values.length; - } - - if (inAllMeshes) { - attributesInAllMeshes[name] = new GeometryAttribute({ - componentDatatype : attribute.componentDatatype, - componentsPerAttribute : attribute.componentsPerAttribute, - normalize : attribute.normalize, - values : attribute.componentDatatype.createTypedArray(numberOfComponents) - }); - } - } - } - - return attributesInAllMeshes; - } - var scratch = new Cartesian3(); function transformPoint(matrix, attribute) { @@ -698,6 +654,50 @@ define([ return mesh; }; + function findAttributesInAllMeshes(meshes) { + var length = meshes.length; + + var attributesInAllMeshes = {}; + + var attributes0 = meshes[0].attributes; + var name; + + for (name in attributes0) { + if (attributes0.hasOwnProperty(name)) { + var attribute = attributes0[name]; + var numberOfComponents = attribute.values.length; + var inAllMeshes = true; + + // Does this same attribute exist in all meshes? + for (var i = 1; i < length; ++i) { + var otherAttribute = meshes[i].attributes[name]; + + if ((typeof otherAttribute === 'undefined') || + (attribute.componentDatatype !== otherAttribute.componentDatatype) || + (attribute.componentsPerAttribute !== otherAttribute.componentsPerAttribute) || + (attribute.normalize !== otherAttribute.normalize)) { + + inAllMeshes = false; + break; + } + + numberOfComponents += otherAttribute.values.length; + } + + if (inAllMeshes) { + attributesInAllMeshes[name] = new GeometryAttribute({ + componentDatatype : attribute.componentDatatype, + componentsPerAttribute : attribute.componentsPerAttribute, + normalize : attribute.normalize, + values : attribute.componentDatatype.createTypedArray(numberOfComponents) + }); + } + } + } + + return attributesInAllMeshes; + } + /** * DOC_TBA * From 208162cabe53601d96c954b5ddf262d72634df3c Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 16 May 2013 19:53:11 -0400 Subject: [PATCH 026/306] Add tangent and binormal attributes to BoxGeometry. --- Apps/CesiumViewer/CesiumViewer.js | 37 +++++++-- Source/Core/BoxGeometry.js | 92 +++++++++++++++++++++- Source/Core/VertexFormat.js | 8 ++ Source/Shaders/DefaultAppearanceAllFS.glsl | 30 +++++++ Source/Shaders/DefaultAppearanceAllVS.glsl | 28 +++++++ 5 files changed, 186 insertions(+), 9 deletions(-) create mode 100644 Source/Shaders/DefaultAppearanceAllFS.glsl create mode 100644 Source/Shaders/DefaultAppearanceAllVS.glsl diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index db73b658b212..f8c7238368c4 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -22,6 +22,8 @@ define([ 'Scene/Primitive', 'Scene/Appearance', 'Scene/Material', + 'Shaders/DefaultAppearanceAllFS', + 'Shaders/DefaultAppearanceAllVS', 'Widgets/Dojo/checkForChromeFrame', 'Widgets/Dojo/CesiumViewerWidget' ], function( @@ -47,6 +49,8 @@ define([ Primitive, Appearance, Material, + DefaultAppearanceAllFS, + DefaultAppearanceAllVS, checkForChromeFrame, CesiumViewerWidget) { "use strict"; @@ -97,19 +101,35 @@ define([ pickData : 'mesh3' }); -// var primitive = new Primitive([mesh3], Appearance.CLOSED_TRANSLUCENT); - var primitive = new Primitive([mesh, mesh2, mesh3], Appearance.CLOSED_TRANSLUCENT); - widget.scene.getPrimitives().add(primitive); + //var primitive = new Primitive([mesh3], Appearance.CLOSED_TRANSLUCENT); + //var primitive = new Primitive([mesh, mesh2, mesh3], Appearance.CLOSED_TRANSLUCENT); + //widget.scene.getPrimitives().add(primitive); var m = new Material({ context : widget.scene.getContext(), fabric : { - type : 'Image', - uniforms : { - image : '../Sandcastle/images/Cesium_Logo_Color.jpg' + materials : { + diffuseMaterial : { + type : 'DiffuseMap', + uniforms : { + image : '../Sandcastle/images/bumpmap.png' + } + }, + normalMap : { + type : 'NormalMap', + uniforms : { + image : '../Sandcastle/images/normalmap.png', + strength : 0.6 + } + } + }, + components : { + diffuse : 'diffuseMaterial.diffuse', + specular : 0.01, + normal : 'normalMap.normal' } } - }); + }); var rs = { depthTest : { enabled : true @@ -117,10 +137,13 @@ define([ }; var appearance = new Appearance({ material : m, + vertexShaderSource : DefaultAppearanceAllVS, + fragmentShaderSource : DefaultAppearanceAllFS, renderState : rs }); var mesh4 = new BoxGeometry({ + vertexFormat : VertexFormat.ALL, dimensions : new Cartesian3(1000000.0, 1000000.0, 1000000.0), modelMatrix : Matrix4.multiplyByTranslation(Transforms.eastNorthUpToFixedFrame( Ellipsoid.WGS84.cartographicToCartesian(Cartographic.fromDegrees(-75.59777, 40.03883))), new Cartesian3(0.0, 0.0, 4500000.0)), diff --git a/Source/Core/BoxGeometry.js b/Source/Core/BoxGeometry.js index 5811dc8f039f..45691c89cac9 100644 --- a/Source/Core/BoxGeometry.js +++ b/Source/Core/BoxGeometry.js @@ -26,7 +26,7 @@ define([ /** * DOC_TBA * - * @alias EllipsoidGeometry + * @alias BoxGeometry * @constructor * * @exception {DeveloperError} All dimensions components must be greater than or equal to zero. @@ -150,6 +150,94 @@ define([ }); } + if (vertexFormat.tangent) { + attributes.tangent = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : [ + // +z face + 1.0, 0.0, 0.0, + 1.0, 0.0, 0.0, + 1.0, 0.0, 0.0, + 1.0, 0.0, 0.0, + + // -z face + -1.0, 0.0, 0.0, + -1.0, 0.0, 0.0, + -1.0, 0.0, 0.0, + -1.0, 0.0, 0.0, + + // +x face + 0.0, 0.0, -1.0, + 0.0, 0.0, -1.0, + 0.0, 0.0, -1.0, + 0.0, 0.0, -1.0, + + // -x face + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, + + // +y face + 1.0, 0.0, 0.0, + 1.0, 0.0, 0.0, + 1.0, 0.0, 0.0, + 1.0, 0.0, 0.0, + + // -y face + -1.0, 0.0, 0.0, + -1.0, 0.0, 0.0, + -1.0, 0.0, 0.0, + -1.0, 0.0, 0.0 + ] + }); + } + + if (vertexFormat.binormal) { + attributes.binormal = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : [ + // +z face + 0.0, -1.0, 0.0, + 0.0, -1.0, 0.0, + 0.0, -1.0, 0.0, + 0.0, -1.0, 0.0, + + // -z face + 0.0, -1.0, 0.0, + 0.0, -1.0, 0.0, + 0.0, -1.0, 0.0, + 0.0, -1.0, 0.0, + + // +x face + 0.0, -1.0, 0.0, + 0.0, -1.0, 0.0, + 0.0, -1.0, 0.0, + 0.0, -1.0, 0.0, + + // -x face + 0.0, -1.0, 0.0, + 0.0, -1.0, 0.0, + 0.0, -1.0, 0.0, + 0.0, -1.0, 0.0, + + // +y face + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, + + // -y face + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0 + ] + }); + } + if (vertexFormat.st) { attributes.st = new GeometryAttribute({ @@ -222,7 +310,7 @@ define([ // -y face 20 + 0, 20 + 1, 20 + 2, - 20 + 0, 20 + 2, 20 + 3, + 20 + 0, 20 + 2, 20 + 3 ] })); } else { diff --git a/Source/Core/VertexFormat.js b/Source/Core/VertexFormat.js index f594f6f8351c..0cc9bbd7bfca 100644 --- a/Source/Core/VertexFormat.js +++ b/Source/Core/VertexFormat.js @@ -57,5 +57,13 @@ define([ textureCoordinates : false })); + /** + * DOC_TBA + */ + VertexFormat.ALL = freezeObject(new VertexFormat({ + binormal : true, + tangent : true + })); + return VertexFormat; }); \ No newline at end of file diff --git a/Source/Shaders/DefaultAppearanceAllFS.glsl b/Source/Shaders/DefaultAppearanceAllFS.glsl new file mode 100644 index 000000000000..010f1ba4b81e --- /dev/null +++ b/Source/Shaders/DefaultAppearanceAllFS.glsl @@ -0,0 +1,30 @@ +varying vec3 v_normalEC; +varying vec3 v_tangentEC; +varying vec3 v_binormalEC; +varying vec3 v_positionEC; +varying vec2 v_st; + +void main() +{ + vec3 positionToEyeEC = -v_positionEC; + + vec3 normalEC = normalize(v_normalEC); + vec3 tangentEC = normalize(v_tangentEC); + vec3 binormalEC = normalize(v_binormalEC); + mat3 tangentToEyeMatrix = mat3( + tangentEC.x, tangentEC.y, tangentEC.z, + binormalEC.x, binormalEC.y, binormalEC.z, + normalEC.x, normalEC.y, normalEC.z); + + czm_materialInput materialInput; + materialInput.normalEC = normalEC; + materialInput.tangentToEyeMatrix = tangentToEyeMatrix; + materialInput.positionToEyeEC = positionToEyeEC; + materialInput.st = v_st; + czm_material material = czm_getMaterial(materialInput); + + //material.specular = 0.2; + //material.shininess = 10.0; + + gl_FragColor = czm_phong(normalize(positionToEyeEC), material); +} diff --git a/Source/Shaders/DefaultAppearanceAllVS.glsl b/Source/Shaders/DefaultAppearanceAllVS.glsl new file mode 100644 index 000000000000..75b2321ba248 --- /dev/null +++ b/Source/Shaders/DefaultAppearanceAllVS.glsl @@ -0,0 +1,28 @@ +attribute vec3 positionHigh; +attribute vec3 positionLow; +attribute vec3 normal; +attribute vec3 tangent; +attribute vec3 binormal; +attribute vec2 st; +attribute vec4 pickColor; + +varying vec3 v_normalEC; +varying vec3 v_tangentEC; +varying vec3 v_binormalEC; +varying vec3 v_positionEC; +varying vec2 v_st; +varying vec4 czm_pickColor; + +void main() +{ + vec4 p = czm_translateRelativeToEye(positionHigh, positionLow); + + v_normalEC = czm_normal * normal; // normal in eye coordinates + v_tangentEC = czm_normal * tangent; // tangent in eye coordinates + v_binormalEC = czm_normal * binormal; // binormal in eye coordinates + v_positionEC = (czm_modelViewRelativeToEye * p).xyz; // position in eye coordinates + v_st = st; + czm_pickColor = pickColor; + + gl_Position = czm_modelViewProjectionRelativeToEye * p; +} From fae9bbb45dd2255110159fd2bb8ea9020236a104 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 16 May 2013 20:12:38 -0400 Subject: [PATCH 027/306] Start moving EllipsoidGeometry to use a VertexFormat. --- Source/Core/EllipsoidGeometry.js | 242 ++++++++++++++++--------------- 1 file changed, 128 insertions(+), 114 deletions(-) diff --git a/Source/Core/EllipsoidGeometry.js b/Source/Core/EllipsoidGeometry.js index b628f3cad72b..669aca5ab25e 100644 --- a/Source/Core/EllipsoidGeometry.js +++ b/Source/Core/EllipsoidGeometry.js @@ -9,7 +9,8 @@ define([ './PrimitiveType', './BoundingSphere', './GeometryAttribute', - './GeometryIndices' + './GeometryIndices', + './VertexFormat' ], function( defaultValue, DeveloperError, @@ -20,7 +21,8 @@ define([ PrimitiveType, BoundingSphere, GeometryAttribute, - GeometryIndices) { + GeometryIndices, + VertexFormat) { "use strict"; /** @@ -37,6 +39,8 @@ define([ var ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.UNIT_SPHERE); var numberOfPartitions = defaultValue(options.numberOfPartitions, 32); + var vertexFormat = defaultValue(options.vertexFormat, VertexFormat.DEFAULT); + if (numberOfPartitions <= 0) { throw new DeveloperError('options.numberOfPartitions must be greater than zero.'); } @@ -44,77 +48,6 @@ define([ var positions = []; var indices = []; - function addEdgePositions(i0, i1) { - var indices = []; - indices[0] = i0; - indices[2 + (numberOfPartitions - 1) - 1] = i1; - - var origin = positions[i0]; - var direction = positions[i1].subtract(positions[i0]); - - for ( var i = 1; i < numberOfPartitions; ++i) { - var delta = i / numberOfPartitions; - - indices[i] = positions.length; - positions.push(origin.add(direction.multiplyByScalar(delta))); - } - - return indices; - } - - function addFaceTriangles(leftBottomToTop, bottomLeftToRight, rightBottomToTop, topLeftToRight) { - var origin = positions[bottomLeftToRight[0]]; - var x = positions[bottomLeftToRight[bottomLeftToRight.length - 1]].subtract(origin); - var y = positions[topLeftToRight[0]].subtract(origin); - - var bottomIndicesBuffer = []; - var topIndicesBuffer = []; - - var bottomIndices = bottomLeftToRight; - var topIndices = topIndicesBuffer; - - for ( var j = 1; j <= numberOfPartitions; ++j) { - if (j !== numberOfPartitions) { - if (j !== 1) { - // - // This copy could be avoided by ping ponging buffers. - // - bottomIndicesBuffer = topIndicesBuffer.slice(0); - bottomIndices = bottomIndicesBuffer; - } - - topIndicesBuffer[0] = leftBottomToTop[j]; - topIndicesBuffer[numberOfPartitions] = rightBottomToTop[j]; - - var deltaY = j / numberOfPartitions; - var offsetY = y.multiplyByScalar(deltaY); - - for ( var i = 1; i < numberOfPartitions; ++i) { - var deltaX = i / numberOfPartitions; - var offsetX = x.multiplyByScalar(deltaX); - - topIndicesBuffer[i] = positions.length; - positions.push(origin.add(offsetX).add(offsetY)); - } - } else { - if (j !== 1) { - bottomIndices = topIndicesBuffer; - } - topIndices = topLeftToRight; - } - - for ( var k = 0; k < numberOfPartitions; ++k) { - indices.push(bottomIndices[k]); - indices.push(bottomIndices[k + 1]); - indices.push(topIndices[k + 1]); - - indices.push(bottomIndices[k]); - indices.push(topIndices[k + 1]); - indices.push(topIndices[k]); - } - } - } - // // Initial cube. In the plane, z = -1: // @@ -145,52 +78,62 @@ define([ // 4 -> 5, 5 -> 6, 6 -> 7, 7 -> 4. Plane z = 1 // 0 -> 4, 1 -> 5, 2 -> 6, 3 -> 7. From plane z = -1 to plane z - 1 // - var edge0to1 = addEdgePositions(0, 1); - var edge1to2 = addEdgePositions(1, 2); - var edge2to3 = addEdgePositions(2, 3); - var edge3to0 = addEdgePositions(3, 0); - - var edge4to5 = addEdgePositions(4, 5); - var edge5to6 = addEdgePositions(5, 6); - var edge6to7 = addEdgePositions(6, 7); - var edge7to4 = addEdgePositions(7, 4); - - var edge0to4 = addEdgePositions(0, 4); - var edge1to5 = addEdgePositions(1, 5); - var edge2to6 = addEdgePositions(2, 6); - var edge3to7 = addEdgePositions(3, 7); - - addFaceTriangles(edge0to4, edge0to1, edge1to5, edge4to5); // Q3 Face - addFaceTriangles(edge1to5, edge1to2, edge2to6, edge5to6); // Q4 Face - addFaceTriangles(edge2to6, edge2to3, edge3to7, edge6to7); // Q1 Face - addFaceTriangles(edge3to7, edge3to0, edge0to4, edge7to4); // Q2 Face - addFaceTriangles(edge7to4.slice(0).reverse(), edge4to5, edge5to6, edge6to7.slice(0).reverse()); // Plane z = 1 - addFaceTriangles(edge1to2, edge0to1.slice(0).reverse(), edge3to0.slice(0).reverse(), edge2to3); // Plane z = -1 - - // Expand cube into ellipsoid and flatten values - var radii = ellipsoid.getRadii(); - var length = positions.length; - var q = 0; - var flattenedPositions = new Array(length * 3); - for ( var i = 0; i < length; ++i) { - var item = positions[i]; - Cartesian3.normalize(item, item); - Cartesian3.multiplyComponents(item, radii, item); - flattenedPositions[q++] = item.x; - flattenedPositions[q++] = item.y; - flattenedPositions[q++] = item.z; + var edge0to1 = addEdgePositions(0, 1, numberOfPartitions, positions); + var edge1to2 = addEdgePositions(1, 2, numberOfPartitions, positions); + var edge2to3 = addEdgePositions(2, 3, numberOfPartitions, positions); + var edge3to0 = addEdgePositions(3, 0, numberOfPartitions, positions); + + var edge4to5 = addEdgePositions(4, 5, numberOfPartitions, positions); + var edge5to6 = addEdgePositions(5, 6, numberOfPartitions, positions); + var edge6to7 = addEdgePositions(6, 7, numberOfPartitions, positions); + var edge7to4 = addEdgePositions(7, 4, numberOfPartitions, positions); + + var edge0to4 = addEdgePositions(0, 4, numberOfPartitions, positions); + var edge1to5 = addEdgePositions(1, 5, numberOfPartitions, positions); + var edge2to6 = addEdgePositions(2, 6, numberOfPartitions, positions); + var edge3to7 = addEdgePositions(3, 7, numberOfPartitions, positions); + + // Q3 Face + addFaceTriangles(edge0to4, edge0to1, edge1to5, edge4to5, numberOfPartitions, positions, indices); + // Q4 Face + addFaceTriangles(edge1to5, edge1to2, edge2to6, edge5to6, numberOfPartitions, positions, indices); + // Q1 Face + addFaceTriangles(edge2to6, edge2to3, edge3to7, edge6to7, numberOfPartitions, positions, indices); + // Q2 Face + addFaceTriangles(edge3to7, edge3to0, edge0to4, edge7to4, numberOfPartitions, positions, indices); + // Plane z = 1 + addFaceTriangles(edge7to4.slice(0).reverse(), edge4to5, edge5to6, edge6to7.slice(0).reverse(), numberOfPartitions, positions, indices); + // Plane z = -1 + addFaceTriangles(edge1to2, edge0to1.slice(0).reverse(), edge3to0.slice(0).reverse(), edge2to3, numberOfPartitions, positions, indices); + + var attributes = {}; + + if (vertexFormat.position) { + // Expand cube into ellipsoid and flatten values + var radii = ellipsoid.getRadii(); + var length = positions.length; + var q = 0; + var flattenedPositions = new Array(length * 3); + for ( var i = 0; i < length; ++i) { + var item = positions[i]; + Cartesian3.normalize(item, item); + Cartesian3.multiplyComponents(item, radii, item); + flattenedPositions[q++] = item.x; + flattenedPositions[q++] = item.y; + flattenedPositions[q++] = item.z; + } + + attributes.position = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : flattenedPositions + }); } /** * DOC_TBA */ - this.attributes = { - position : new GeometryAttribute({ - componentDatatype : ComponentDatatype.FLOAT, - componentsPerAttribute : 3, - values : flattenedPositions - }) - }; + this.attributes = attributes; /** * DOC_TBA @@ -218,5 +161,76 @@ define([ this.pickData = options.pickData; }; + function addEdgePositions(i0, i1, numberOfPartitions, positions) { + var indices = []; + indices[0] = i0; + indices[2 + (numberOfPartitions - 1) - 1] = i1; + + var origin = positions[i0]; + var direction = positions[i1].subtract(positions[i0]); + + for ( var i = 1; i < numberOfPartitions; ++i) { + var delta = i / numberOfPartitions; + + indices[i] = positions.length; + positions.push(origin.add(direction.multiplyByScalar(delta))); + } + + return indices; + } + + function addFaceTriangles(leftBottomToTop, bottomLeftToRight, rightBottomToTop, topLeftToRight, numberOfPartitions, positions, indices) { + var origin = positions[bottomLeftToRight[0]]; + var x = positions[bottomLeftToRight[bottomLeftToRight.length - 1]].subtract(origin); + var y = positions[topLeftToRight[0]].subtract(origin); + + var bottomIndicesBuffer = []; + var topIndicesBuffer = []; + + var bottomIndices = bottomLeftToRight; + var topIndices = topIndicesBuffer; + + for ( var j = 1; j <= numberOfPartitions; ++j) { + if (j !== numberOfPartitions) { + if (j !== 1) { + // + // This copy could be avoided by ping ponging buffers. + // + bottomIndicesBuffer = topIndicesBuffer.slice(0); + bottomIndices = bottomIndicesBuffer; + } + + topIndicesBuffer[0] = leftBottomToTop[j]; + topIndicesBuffer[numberOfPartitions] = rightBottomToTop[j]; + + var deltaY = j / numberOfPartitions; + var offsetY = y.multiplyByScalar(deltaY); + + for ( var i = 1; i < numberOfPartitions; ++i) { + var deltaX = i / numberOfPartitions; + var offsetX = x.multiplyByScalar(deltaX); + + topIndicesBuffer[i] = positions.length; + positions.push(origin.add(offsetX).add(offsetY)); + } + } else { + if (j !== 1) { + bottomIndices = topIndicesBuffer; + } + topIndices = topLeftToRight; + } + + for ( var k = 0; k < numberOfPartitions; ++k) { + indices.push(bottomIndices[k]); + indices.push(bottomIndices[k + 1]); + indices.push(topIndices[k + 1]); + + indices.push(bottomIndices[k]); + indices.push(topIndices[k + 1]); + indices.push(topIndices[k]); + } + } + } + return EllipsoidGeometry; }); \ No newline at end of file From 288b20a2edcca44f26e0e21fc5daf432ee2c7908 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 16 May 2013 20:19:33 -0400 Subject: [PATCH 028/306] Add normals to EllipsoidGeometry. --- Source/Core/EllipsoidGeometry.js | 35 ++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/Source/Core/EllipsoidGeometry.js b/Source/Core/EllipsoidGeometry.js index 669aca5ab25e..9c07a57f6a72 100644 --- a/Source/Core/EllipsoidGeometry.js +++ b/Source/Core/EllipsoidGeometry.js @@ -108,19 +108,23 @@ define([ var attributes = {}; + var length = positions.length; + var i; + var j; + if (vertexFormat.position) { // Expand cube into ellipsoid and flatten values var radii = ellipsoid.getRadii(); - var length = positions.length; - var q = 0; var flattenedPositions = new Array(length * 3); - for ( var i = 0; i < length; ++i) { + + j = 0; + for (i = 0; i < length; ++i) { var item = positions[i]; Cartesian3.normalize(item, item); Cartesian3.multiplyComponents(item, radii, item); - flattenedPositions[q++] = item.x; - flattenedPositions[q++] = item.y; - flattenedPositions[q++] = item.z; + flattenedPositions[j++] = item.x; + flattenedPositions[j++] = item.y; + flattenedPositions[j++] = item.z; } attributes.position = new GeometryAttribute({ @@ -130,6 +134,25 @@ define([ }); } + if (vertexFormat.normal) { + var normals = new Array(length * 3); + var normal = new Cartesian3(); + + j = 0; + for (i = 0; i < length; ++i) { + ellipsoid.geodeticSurfaceNormal(positions[i], normal); + normals[j++] = normal.x; + normals[j++] = normal.y; + normals[j++] = normal.z; + } + + attributes.normal = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : normals + }); + } + /** * DOC_TBA */ From e6412a9cd22b7cde930428dc2a1c420f18ecb30e Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Fri, 17 May 2013 08:01:14 -0400 Subject: [PATCH 029/306] Added vertex cache optimization --- Apps/CesiumViewer/CesiumViewer.js | 14 +++++++++----- Source/Scene/Primitive.js | 27 +++++++++++++++++++++------ 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index db73b658b212..b38cf736b7ee 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -96,9 +96,10 @@ define([ Ellipsoid.WGS84.cartographicToCartesian(Cartographic.fromDegrees(-75.59777, 40.03883))), new Cartesian3(0.0, 0.0, 3000000.0)), pickData : 'mesh3' }); - -// var primitive = new Primitive([mesh3], Appearance.CLOSED_TRANSLUCENT); - var primitive = new Primitive([mesh, mesh2, mesh3], Appearance.CLOSED_TRANSLUCENT); + var primitive = new Primitive({ + geometries : [mesh, mesh2, mesh3], + appearance : Appearance.CLOSED_TRANSLUCENT + }); widget.scene.getPrimitives().add(primitive); var m = new Material({ @@ -127,10 +128,13 @@ define([ pickData : 'mesh4' }); - var primitive2 = new Primitive(mesh4, appearance); + var primitive2 = new Primitive({ + geometries : mesh4, + appearance :appearance, + vertexCacheOptimize : false + }); widget.scene.getPrimitives().add(primitive2); - var handler = new ScreenSpaceEventHandler(scene.getCanvas()); handler.setInputAction( function (movement) { diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index c80525df6fe3..e380a3c46f06 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -1,5 +1,6 @@ /*global define*/ define([ + '../Core/defaultValue', '../Core/destroyObject', '../Core/Matrix4', '../Core/Color', @@ -16,6 +17,7 @@ define([ '../Renderer/createPickFragmentShaderSource', './SceneMode' ], function( + defaultValue, destroyObject, Matrix4, Color, @@ -36,16 +38,18 @@ define([ /** * DOC_TBA */ - var Primitive = function(geometries, appearance) { + var Primitive = function(options) { + options = defaultValue(options, defaultValue.EMPTY_OBJECT); + /** * DOC_TBA */ - this.geometries = geometries; + this.geometries = options.geometries; /** * DOC_TBA */ - this.appearance = appearance; + this.appearance = options.appearance; /** * DOC_TBA @@ -57,6 +61,8 @@ define([ */ this.show = true; + this._vertexCacheOptimize = defaultValue(options.vertexCacheOptimize, true); + this._sp = undefined; this._rs = undefined; this._va = []; @@ -108,7 +114,7 @@ define([ } } - function processGeometry(primitive, geometries, context) { + function geometryPipeline(primitive, geometries, context) { // Add pickColor attribute if any geometries are pickable if (Geometry.isPickable(geometries)) { addPickColorAttribute(primitive, geometries, context); @@ -148,13 +154,22 @@ define([ if (typeof this._sp === 'undefined') { var geometries = (this.geometries instanceof Array) ? this.geometries : [this.geometries]; - var geometry = processGeometry(this, geometries, context); + var geometry = geometryPipeline(this, geometries, context); // Break into multiple geometries to fit within unsigned short indices if needed var finalGeometries = GeometryFilters.fitToUnsignedShortIndices(geometry); + + length = finalGeometries.length; + if (this._vertexCacheOptimize) { + // Optimize for vertex shader caches + for (i = 0; i < length; ++i) { + GeometryFilters.reorderForPostVertexCache(finalGeometries[i]); + GeometryFilters.reorderForPreVertexCache(finalGeometries[i]); + } + } + var attributeIndices = GeometryFilters.createAttributeIndices(geometry); var va = []; - length = finalGeometries.length; for (i = 0; i < length; ++i) { va.push(context.createVertexArrayFromMesh({ mesh : finalGeometries[i], From cdcb4f5f889408c2ec8989b198f636a325854588 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Fri, 17 May 2013 08:45:23 -0400 Subject: [PATCH 030/306] Added releaseGeometries option --- Apps/CesiumViewer/CesiumViewer.js | 3 ++- Source/Core/GeometryFilters.js | 1 + Source/Scene/Primitive.js | 23 ++++++++++++++--------- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index b38cf736b7ee..cf89f1e140c4 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -131,7 +131,8 @@ define([ var primitive2 = new Primitive({ geometries : mesh4, appearance :appearance, - vertexCacheOptimize : false + vertexCacheOptimize : false, + releaseGeometries : true }); widget.scene.getPrimitives().add(primitive2); diff --git a/Source/Core/GeometryFilters.js b/Source/Core/GeometryFilters.js index 6ce1ff5d4fc3..bd350b1120d6 100644 --- a/Source/Core/GeometryFilters.js +++ b/Source/Core/GeometryFilters.js @@ -647,6 +647,7 @@ define([ if (typeof mesh.boundingSphere !== 'undefined') { Matrix4.multiplyByPoint(mesh.modelMatrix, mesh.boundingSphere.center, mesh.boundingSphere.center); + mesh.boundingSphere.center = Cartesian3.fromCartesian4(mesh.boundingSphere.center); } mesh.modelMatrix = Matrix4.IDENTITY.clone(); diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index e380a3c46f06..04f7703ef59d 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -62,6 +62,7 @@ define([ this.show = true; this._vertexCacheOptimize = defaultValue(options.vertexCacheOptimize, true); + this._releaseGeometries = defaultValue(options.releaseGeometries, false); this._sp = undefined; this._rs = undefined; @@ -130,9 +131,10 @@ define([ var geometry = GeometryFilters.combine(geometries); // Split position for GPU RTE - geometry = GeometryFilters.encodeAttribute(geometry, 'position', 'positionHigh', 'positionLow'); + GeometryFilters.encodeAttribute(geometry, 'position', 'positionHigh', 'positionLow'); - return geometry; + // Break into multiple geometries to fit within unsigned short indices if needed + return GeometryFilters.fitToUnsignedShortIndices(geometry); } /** @@ -141,7 +143,7 @@ define([ Primitive.prototype.update = function(context, frameState, commandList) { if (!this.show || (frameState.mode !== SceneMode.SCENE3D) || - (typeof this.geometries === 'undefined') || + ((typeof this.geometries === 'undefined') && (this._va.length === 0)) || (typeof this.appearance === 'undefined')) { // TODO: support Columbus view and 2D return; @@ -152,11 +154,9 @@ define([ var length; var i; - if (typeof this._sp === 'undefined') { + if (this._va.length === 0) { var geometries = (this.geometries instanceof Array) ? this.geometries : [this.geometries]; - var geometry = geometryPipeline(this, geometries, context); - // Break into multiple geometries to fit within unsigned short indices if needed - var finalGeometries = GeometryFilters.fitToUnsignedShortIndices(geometry); + var finalGeometries = geometryPipeline(this, geometries, context); length = finalGeometries.length; if (this._vertexCacheOptimize) { @@ -167,7 +167,7 @@ define([ } } - var attributeIndices = GeometryFilters.createAttributeIndices(geometry); + var attributeIndices = GeometryFilters.createAttributeIndices(finalGeometries[0]); var va = []; for (i = 0; i < length; ++i) { @@ -193,6 +193,8 @@ define([ this._rs = context.createRenderState(appearance.renderState); for (i = 0; i < length; ++i) { + var geometry = finalGeometries[i]; + var command = new DrawCommand(); // TODO: this assumes indices in the geometries - and only one set command.primitiveType = geometry.indexLists[0].primitiveType; @@ -200,7 +202,6 @@ define([ command.renderState = this._rs; command.shaderProgram = this._sp; command.uniformMap = appearance.material._uniforms; -// TODO: could use bounding volume per geometry command.boundingVolume = geometry.boundingSphere; colorCommands.push(command); @@ -215,6 +216,10 @@ define([ pickCommands.push(pickCommand); } } + + if (this._releaseGeometries) { + this.geometries = undefined; + } } // The geometry is static but the model matrix can change From 513cbece08cf3e2bb827fc3e5a5a613fd6af0b11 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Fri, 17 May 2013 09:09:26 -0400 Subject: [PATCH 031/306] Added transformToWorldCoordinates option --- Apps/CesiumViewer/CesiumViewer.js | 3 ++- Source/Scene/Primitive.js | 37 ++++++++++++++++++++++++++----- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index cf89f1e140c4..ec2889d1247f 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -132,7 +132,8 @@ define([ geometries : mesh4, appearance :appearance, vertexCacheOptimize : false, - releaseGeometries : true + releaseGeometries : true, + transformToWorldCoordinates : false }); widget.scene.getPrimitives().add(primitive2); diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index 04f7703ef59d..9cbd3cb67268 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -63,6 +63,9 @@ define([ this._vertexCacheOptimize = defaultValue(options.vertexCacheOptimize, true); this._releaseGeometries = defaultValue(options.releaseGeometries, false); + // When true, geometry is transformed to world coordinates even if there is a single + // geometry or all geometries are in the same reference frame. + this._transformToWorldCoordinates = defaultValue(options.transformToWorldCoordinates, true); this._sp = undefined; this._rs = undefined; @@ -115,17 +118,41 @@ define([ } } + function transformToWorldCoordinates(primitive, geometries) { + var toWorld = primitive._transformToWorldCoordinates; + var length = geometries.length; + var i; + + if (!toWorld && (length > 1)) { + var modelMatrix = Matrix4.clone(geometries[0].modelMatrix); + + for (i = 1; i < length; ++i) { + if (!Matrix4.equals(modelMatrix, geometries[i])) { + toWorld = true; + break; + } + } + } + + if (toWorld) { + for (i = 0; i < length; ++i) { + GeometryFilters.transformToWorldCoordinates(geometries[i]); + } + } else { + // Leave geometry in local coordinate system; auto update model-matrix. + Matrix4.clone(geometries[0].modelMatrix, primitive.modelMatrix); + } + } + function geometryPipeline(primitive, geometries, context) { // Add pickColor attribute if any geometries are pickable if (Geometry.isPickable(geometries)) { addPickColorAttribute(primitive, geometries, context); } - // Unify to world coordinates before combining. - var length = geometries.length; - for (var i = 0; i < length; ++i) { - GeometryFilters.transformToWorldCoordinates(geometries[i]); - } + // Unify to world coordinates before combining. If there is only one geometry or all + // geometries are in the same (non-world) coordinate system, only combine if the user requested it. + transformToWorldCoordinates(primitive, geometries); // Combine into single geometry for better rendering performance. var geometry = GeometryFilters.combine(geometries); From 25a0025a813465e251b2c490b22d561998a5eaf7 Mon Sep 17 00:00:00 2001 From: hpinkos Date: Fri, 17 May 2013 12:13:05 -0400 Subject: [PATCH 032/306] first pass at GeometryFilters.computeNormals --- Source/Core/GeometryFilters.js | 95 +++++++++++++++++++++++++++++++ Specs/Core/GeometryFiltersSpec.js | 35 ++++++++++++ 2 files changed, 130 insertions(+) diff --git a/Source/Core/GeometryFilters.js b/Source/Core/GeometryFilters.js index 6ce1ff5d4fc3..5dacb8244b63 100644 --- a/Source/Core/GeometryFilters.js +++ b/Source/Core/GeometryFilters.js @@ -853,5 +853,100 @@ define([ }); }; + var normalsPerVertex = []; + var normalsPerTriangle = []; + var normalIndices = []; + var p = new Cartesian3(); + var q = new Cartesian3(); + GeometryFilters.computeNormals = function(vertices, indices, result) { + if (typeof vertices === 'undefined' || vertices.length < 0) { + throw new DeveloperError('vertices is required to have a length greater than zero'); + } + if (typeof indices === 'undefined' || indices.length < 2) { + throw new DeveloperError('indices is requred to have a length greater than two'); + } + if (indices.length % 3 !== 0) { + throw new DeveloperError('length of indices must be a multiple of three'); + } + normalsPerVertex.length = 0; + normalsPerTriangle.length = 0; + var numVertices = vertices.length; + var numIndices = indices.length; + + if (typeof result === 'undefined') { + result = []; + } + + for (var i = 0; i < numVertices; i++) { + normalsPerVertex[i] = { + indexOffset: 0, + count: 0, + currentCount: 0 + }; + } + + var j = 0; + for (i = 0; i < numIndices; i+=3) { + var i0 = indices[i]; + var i1 = indices[i+1]; + var i2 = indices[i+2]; + + var v0 = vertices[i0]; + var v1 = vertices[i1]; + var v2 = vertices[i2]; + + normalsPerVertex[i0].count++; + normalsPerVertex[i1].count++; + normalsPerVertex[i2].count++; + + v1.subtract(v0, p); + v2.subtract(v1, q); + normalsPerTriangle[j] = p.cross(q); + j++; + } + + var indexOffset = 0; + for (i = 0; i < numVertices; i++) { + normalsPerVertex[i].indexOffset += indexOffset; + indexOffset += normalsPerVertex[i].count; + } + + j = 0; + var vertexNormalData; + for (i = 0; i < numIndices; i+=3) { + vertexNormalData = normalsPerVertex[indices[i]]; + var index = vertexNormalData.indexOffset + vertexNormalData.currentCount; + normalIndices[index] = j; + vertexNormalData.currentCount++; + + vertexNormalData = normalsPerVertex[indices[i+1]]; + index = vertexNormalData.indexOffset + vertexNormalData.currentCount; + normalIndices[index] = j; + vertexNormalData.currentCount++; + + vertexNormalData = normalsPerVertex[indices[i+2]]; + index = vertexNormalData.indexOffset + vertexNormalData.currentCount; + normalIndices[index] = j; + vertexNormalData.currentCount++; + + j++; + } + + for (i = 0; i < numVertices; i++) { + vertexNormalData = normalsPerVertex[i]; + if (vertexNormalData.count > 0) { + var normal = new Cartesian3(); + for (j = 0; j < vertexNormalData.count; j++) { + normal.add(normalsPerTriangle[normalIndices[vertexNormalData.indexOffset + j]], normal); + } + result[i] = normal.normalize(); + } else { + result[i] = Cartesian3.UNIT_Z; + } + } + + return result; + }; + return GeometryFilters; }); diff --git a/Specs/Core/GeometryFiltersSpec.js b/Specs/Core/GeometryFiltersSpec.js index 73a3587e43af..a8abde37e832 100644 --- a/Specs/Core/GeometryFiltersSpec.js +++ b/Specs/Core/GeometryFiltersSpec.js @@ -608,4 +608,39 @@ defineSuite([ }).toThrow(); }); + + it('GeometryFilters.computeNormals computes normal for one triangle', function() { + var vertices = []; + var indices = [0, 1, 2]; + + vertices.push(Cartesian3.ZERO); + vertices.push(Cartesian3.UNIT_X); + vertices.push(Cartesian3.UNIT_Y); + + var results = GeometryFilters.computeNormals(vertices, indices); + + expect(results.length).toEqual(3); + expect(results[0]).toEqual(Cartesian3.UNIT_Z); + expect(results[1]).toEqual(Cartesian3.UNIT_Z); + expect(results[2]).toEqual(Cartesian3.UNIT_Z); + }); + + it('GeometryFilters.computeNormals computes normal for two triangles', function() { + var vertices = []; + var indices = [0, 1, 2, 1, 3, 2]; + + vertices.push(Cartesian3.ZERO); + vertices.push(new Cartesian3(1,0,1)); + vertices.push(new Cartesian3(1,1,1)); + vertices.push(new Cartesian3(2,0,0)); + + var results = GeometryFilters.computeNormals(vertices, indices); + + expect(results.length).toEqual(4); + expect(results[0]).toEqual(new Cartesian3(-1, 0, 1).normalize()); + expect(results[1]).toEqual(Cartesian3.UNIT_Z); + expect(results[2]).toEqual(Cartesian3.UNIT_Z); + expect(results[3]).toEqual(new Cartesian3(1, 0, 1).normalize()); + }); + }); \ No newline at end of file From 0d6a5851b41a1cf0bc3d2abdd51abff33deb9f7a Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Fri, 17 May 2013 12:20:51 -0400 Subject: [PATCH 033/306] Added depth-only for primitives that are not pickable --- Source/Scene/CompositePrimitive.js | 3 +- Source/Scene/Primitive.js | 47 ++++++++++++++++++------------ Source/Scene/Scene.js | 2 +- 3 files changed, 30 insertions(+), 22 deletions(-) diff --git a/Source/Scene/CompositePrimitive.js b/Source/Scene/CompositePrimitive.js index f7b978dc4af8..09d4a5633af2 100644 --- a/Source/Scene/CompositePrimitive.js +++ b/Source/Scene/CompositePrimitive.js @@ -400,8 +400,7 @@ define([ var primitives = this._primitives; var length = primitives.length; for (var i = 0; i < length; ++i) { - var primitive = primitives[i]; - primitive.update(context, frameState, commandList); + primitives[i].update(context, frameState, commandList); } }; diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index 9cbd3cb67268..69928fc4837b 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -1,5 +1,6 @@ /*global define*/ define([ + '../Core/clone', '../Core/defaultValue', '../Core/destroyObject', '../Core/Matrix4', @@ -17,6 +18,7 @@ define([ '../Renderer/createPickFragmentShaderSource', './SceneMode' ], function( + clone, defaultValue, destroyObject, Matrix4, @@ -68,7 +70,6 @@ define([ this._transformToWorldCoordinates = defaultValue(options.transformToWorldCoordinates, true); this._sp = undefined; - this._rs = undefined; this._va = []; this._pickSP = undefined; @@ -209,15 +210,29 @@ define([ var appearance = this.appearance; var vs = appearance.vertexShaderSource; var fs = appearance.getFragmentShaderSource(); - var pickable = Geometry.isPickable(geometries); this._va = va; // TODO: recompile on material change. this._sp = context.getShaderCache().replaceShaderProgram(this._sp, appearance.vertexShaderSource, fs, attributeIndices); - if (pickable) { + var rs = context.createRenderState(appearance.renderState); + var pickRS; + + if (Geometry.isPickable(geometries)) { this._pickSP = context.getShaderCache().replaceShaderProgram(this._pickSP, vs, createPickFragmentShaderSource(fs, 'varying'), attributeIndices); + pickRS = rs; + } else { + this._pickSP = context.getShaderCache().replaceShaderProgram(this._pickSP, appearance.vertexShaderSource, fs, attributeIndices); + + // Still render during pick pass, but depth-only. + var appearanceRS = clone(appearance.renderState, true); + appearanceRS.colorMask = { + red : false, + green : false, + blue : false, + alpha : false + }; + pickRS = context.createRenderState(appearanceRS); } - this._rs = context.createRenderState(appearance.renderState); for (i = 0; i < length; ++i) { var geometry = finalGeometries[i]; @@ -226,22 +241,20 @@ define([ // TODO: this assumes indices in the geometries - and only one set command.primitiveType = geometry.indexLists[0].primitiveType; command.vertexArray = this._va[i]; - command.renderState = this._rs; + command.renderState = rs; command.shaderProgram = this._sp; command.uniformMap = appearance.material._uniforms; command.boundingVolume = geometry.boundingSphere; colorCommands.push(command); - if (pickable) { - var pickCommand = new DrawCommand(); - pickCommand.primitiveType = geometry.indexLists[0].primitiveType; - pickCommand.vertexArray = this._va[i]; - pickCommand.renderState = this._rs; - pickCommand.shaderProgram = this._pickSP; - pickCommand.uniformMap = appearance.material._uniforms; - pickCommand.boundingVolume = geometry.boundingSphere; - pickCommands.push(pickCommand); - } + var pickCommand = new DrawCommand(); + pickCommand.primitiveType = geometry.indexLists[0].primitiveType; + pickCommand.vertexArray = this._va[i]; + pickCommand.renderState = pickRS; + pickCommand.shaderProgram = this._pickSP; + pickCommand.uniformMap = appearance.material._uniforms; + pickCommand.boundingVolume = geometry.boundingSphere; + pickCommands.push(pickCommand); } if (this._releaseGeometries) { @@ -254,10 +267,6 @@ define([ length = colorCommands.length; for (var i = 0; i < length; ++i) { colorCommands[i].modelMatrix = this.modelMatrix; - } - - length = pickCommands.length; - for (var i = 0; i < length; ++i) { pickCommands[i].modelMatrix = this.modelMatrix; } diff --git a/Source/Scene/Scene.js b/Source/Scene/Scene.js index f176b2149781..a817a9db6a7a 100644 --- a/Source/Scene/Scene.js +++ b/Source/Scene/Scene.js @@ -475,7 +475,7 @@ define([ for (var i = 0; i < numFrustums; ++i) { clearDepthStencil.execute(context, passState); - var index = numFrustums - i - 1.0; + var index = numFrustums - i - 1; var frustumCommands = frustumCommandsList[index]; frustum.near = frustumCommands.near; frustum.far = frustumCommands.far; From ad91802e1efd14332f2acc4cb7c595d1ccd13281 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Fri, 17 May 2013 14:23:38 -0400 Subject: [PATCH 034/306] Added support for OES_element_index_uint --- CHANGES.md | 1 + Source/Core/Geometry.js | 25 ++++++++++++++++++++++ Source/Core/GeometryFilters.js | 20 ++--------------- Source/Core/IndexDatatype.js | 23 +++++++++++++++++++- Source/Renderer/Context.js | 39 +++++++++++++++++++++++++++------- Source/Scene/Primitive.js | 9 ++++++-- Specs/Renderer/ContextSpec.js | 16 ++++++++++++++ 7 files changed, 104 insertions(+), 29 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index ca4e3e5ec903..375e4e593609 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -18,6 +18,7 @@ Beta Releases * Improved the performance of drawing polygons created with `configureFromPolygonHierarchy`. * Added `GeometryFilters.combine` to combine meshes for better batching. * Added `BoundingSphere.fromEllipsoid`. +* Added renderer support for `OES_element_index_uint`, which can improve performance by reducing batch sizes. ### b17 - 2013-06-03 diff --git a/Source/Core/Geometry.js b/Source/Core/Geometry.js index 1c8706e97d6b..404ef90b7bae 100644 --- a/Source/Core/Geometry.js +++ b/Source/Core/Geometry.js @@ -66,5 +66,30 @@ define([ return pickable; }; + /** + * DOC_TBA + * + * @exception {DeveloperError} geometries is required. + */ + Geometry.computeNumberOfVertices = function(geometry) { + if (typeof geometry === 'undefined') { + throw new DeveloperError('geometry is required.'); + } + + var numberOfVertices = -1; + for ( var property in geometry.attributes) { + if (geometry.attributes.hasOwnProperty(property) && geometry.attributes[property].values) { + var attribute = geometry.attributes[property]; + var num = attribute.values.length / attribute.componentsPerAttribute; + if ((numberOfVertices !== num) && (numberOfVertices !== -1)) { + throw new DeveloperError('All attribute lists must have the same number of attributes.'); + } + numberOfVertices = num; + } + } + + return numberOfVertices; + }; + return Geometry; }); diff --git a/Source/Core/GeometryFilters.js b/Source/Core/GeometryFilters.js index bd350b1120d6..ad2eb9fe2188 100644 --- a/Source/Core/GeometryFilters.js +++ b/Source/Core/GeometryFilters.js @@ -173,22 +173,6 @@ define([ return mappedIndices; }; - GeometryFilters._computeNumberOfAttributes = function(mesh) { - var numberOfVertices = -1; - for ( var property in mesh.attributes) { - if (mesh.attributes.hasOwnProperty(property) && mesh.attributes[property].values) { - var attribute = mesh.attributes[property]; - var num = attribute.values.length / attribute.componentsPerAttribute; - if ((numberOfVertices !== num) && (numberOfVertices !== -1)) { - throw new DeveloperError('All mesh attribute lists must have the same number of attributes.'); - } - numberOfVertices = num; - } - } - - return numberOfVertices; - }; - /** * Reorders a mesh's indices to achieve better performance from the GPU's pre-vertex-shader cache. * Each list of indices in the mesh's indexList is reordered to keep the same index-vertex correspondence. @@ -210,7 +194,7 @@ define([ */ GeometryFilters.reorderForPreVertexCache = function(mesh) { if (typeof mesh !== 'undefined') { - var numVertices = GeometryFilters._computeNumberOfAttributes(mesh); + var numVertices = Geometry.computeNumberOfVertices(mesh); var indexCrossReferenceOldToNew = []; for ( var i = 0; i < numVertices; i++) { @@ -390,7 +374,7 @@ define([ if (typeof mesh !== 'undefined') { GeometryFilters._verifyTrianglesPrimitiveType(mesh.indexLists); - var numberOfVertices = GeometryFilters._computeNumberOfAttributes(mesh); + var numberOfVertices = Geometry.computeNumberOfVertices(mesh); // If there's an index list and more than 64K attributes, it is possible that // some indices are outside the range of unsigned short [0, 64K - 1] diff --git a/Source/Core/IndexDatatype.js b/Source/Core/IndexDatatype.js index b30e5432751b..a3c0aa5fe801 100644 --- a/Source/Core/IndexDatatype.js +++ b/Source/Core/IndexDatatype.js @@ -15,13 +15,34 @@ define(['./Enumeration'], function(Enumeration) { * @type {Enumeration} */ UNSIGNED_BYTE : new Enumeration(0x1401, 'UNSIGNED_BYTE'), + + /** + * DOC_TBA + * + * @constant + * @type {Enumeration} + */ + UNSIGNED_SHORT : new Enumeration(0x1403, 'UNSIGNED_SHORT'), /** * DOC_TBA * * @constant * @type {Enumeration} */ - UNSIGNED_SHORT : new Enumeration(0x1403, 'UNSIGNED_SHORT') + UNSIGNED_INT : new Enumeration(0x1405, 'UNSIGNED_INT') + }; + + IndexDatatype.UNSIGNED_BYTE.sizeInBytes = Uint8Array.BYTES_PER_ELEMENT; + IndexDatatype.UNSIGNED_SHORT.sizeInBytes = Uint16Array.BYTES_PER_ELEMENT; + IndexDatatype.UNSIGNED_INT.sizeInBytes = Uint32Array.BYTES_PER_ELEMENT; + + /** + * DOC_TBA + */ + IndexDatatype.validate = function(indexDatatype) { + return ((indexDatatype === IndexDatatype.UNSIGNED_BYTE) || + (indexDatatype === IndexDatatype.UNSIGNED_SHORT) || + (indexDatatype === IndexDatatype.UNSIGNED_INT)); }; return IndexDatatype; diff --git a/Source/Renderer/Context.js b/Source/Renderer/Context.js index d6ba144dfb3d..f38165efd2b0 100644 --- a/Source/Renderer/Context.js +++ b/Source/Renderer/Context.js @@ -7,6 +7,7 @@ define([ '../Core/IndexDatatype', '../Core/RuntimeError', '../Core/PrimitiveType', + '../Core/Geometry', '../Core/createGuid', '../Core/Matrix4', './Buffer', @@ -40,6 +41,7 @@ define([ IndexDatatype, RuntimeError, PrimitiveType, + Geometry, createGuid, Matrix4, Buffer, @@ -222,6 +224,7 @@ define([ // Query and initialize extensions this._standardDerivatives = gl.getExtension('OES_standard_derivatives'); + this._elementIndexUint = gl.getExtension('OES_element_index_uint'); this._depthTexture = gl.getExtension('WEBKIT_WEBGL_depth_texture') || gl.getExtension('MOZ_WEBGL_depth_texture'); this._textureFloat = gl.getExtension('OES_texture_float'); var textureFilterAnisotropic = gl.getExtension('EXT_texture_filter_anisotropic') || gl.getExtension('WEBKIT_EXT_texture_filter_anisotropic') || gl.getExtension('MOZ_EXT_texture_filter_anisotropic'); @@ -687,6 +690,21 @@ define([ return !!this._standardDerivatives; }; + /** + * Returns true if the OES_element_index_uint extension is supported. This + * extension allows the use of unsigned int indices, which can improve performance by + * eliminating batch breaking caused by unsigned short indices. + * + * @memberof Context + * + * @returns {Boolean} true if OES_element_index_uint is supported; otherwise, false. + * + * @see OES_element_index_uint + */ + Context.prototype.getElementIndexUint = function() { + return !!this._elementIndexUint; + }; + /** * Returns true if WEBGL_depth_texture is supported. This extension provides * access to depth textures that, for example, can be attached to framebuffers for shadow mapping. @@ -1037,6 +1055,7 @@ define([ * * @return {IndexBuffer} The index buffer, ready to be attached to a vertex array. * + * @exception {RuntimeError} IndexDatatype.UNSIGNED_INT requires OES_element_index_uint, which is not supported on this system. * @exception {DeveloperError} The size in bytes must be greater than zero. * @exception {DeveloperError} Invalid usage. * @exception {DeveloperError} Invalid indexDatatype. @@ -1062,16 +1081,16 @@ define([ * BufferUsage.STATIC_DRAW, IndexDatatype.UNSIGNED_SHORT) */ Context.prototype.createIndexBuffer = function(typedArrayOrSizeInBytes, usage, indexDatatype) { - var bytesPerIndex; - - if (indexDatatype === IndexDatatype.UNSIGNED_BYTE) { - bytesPerIndex = Uint8Array.BYTES_PER_ELEMENT; - } else if (indexDatatype === IndexDatatype.UNSIGNED_SHORT) { - bytesPerIndex = Uint16Array.BYTES_PER_ELEMENT; - } else { + if (!IndexDatatype.validate(indexDatatype)) { throw new DeveloperError('Invalid indexDatatype.'); } + if ((indexDatatype === IndexDatatype.UNSIGNED_INT) && !this.getElementIndexUint()) { + throw new RuntimeError('IndexDatatype.UNSIGNED_INT requires OES_element_index_uint, which is not supported on this system.'); + } + + var bytesPerIndex = indexDatatype.sizeInBytes; + var gl = this._gl; var buffer = createBuffer(gl, gl.ELEMENT_ARRAY_BUFFER, typedArrayOrSizeInBytes, usage); var numberOfIndices = buffer.getSizeInBytes() / bytesPerIndex; @@ -2395,7 +2414,11 @@ define([ var va = createVertexArrayAttributes(this, creationArguments); if (indexLists) { - va.setIndexBuffer(this.createIndexBuffer(new Uint16Array(indexLists[0].values), bufferUsage, IndexDatatype.UNSIGNED_SHORT)); + if ((Geometry.computeNumberOfVertices(mesh) > 64 * 1024) && this.getElementIndexUint()) { + va.setIndexBuffer(this.createIndexBuffer(new Uint32Array(indexLists[0].values), bufferUsage, IndexDatatype.UNSIGNED_INT)); + } else{ + va.setIndexBuffer(this.createIndexBuffer(new Uint16Array(indexLists[0].values), bufferUsage, IndexDatatype.UNSIGNED_SHORT)); + } } return va; diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index 69928fc4837b..d06adb05176f 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -161,8 +161,13 @@ define([ // Split position for GPU RTE GeometryFilters.encodeAttribute(geometry, 'position', 'positionHigh', 'positionLow'); - // Break into multiple geometries to fit within unsigned short indices if needed - return GeometryFilters.fitToUnsignedShortIndices(geometry); + if (!context.getElementIndexUint()) { + // Break into multiple geometries to fit within unsigned short indices if needed + return GeometryFilters.fitToUnsignedShortIndices(geometry); + } + + // Unsigned int indices are supported. No need to break into multiple geometries. + return [geometry]; } /** diff --git a/Specs/Renderer/ContextSpec.js b/Specs/Renderer/ContextSpec.js index 85fd869ac081..21792d351e2a 100644 --- a/Specs/Renderer/ContextSpec.js +++ b/Specs/Renderer/ContextSpec.js @@ -2,12 +2,16 @@ defineSuite([ 'Renderer/Context', 'Core/Color', + 'Core/IndexDatatype', + 'Renderer/BufferUsage', 'Specs/createContext', 'Specs/destroyContext', 'Specs/renderFragment' ], function( Context, Color, + IndexDatatype, + BufferUsage, createContext, destroyContext, renderFragment) { @@ -162,6 +166,18 @@ defineSuite([ } }); + it('gets the element index uint extension', function() { + if (context.getElementIndexUint()) { + var buffer = context.createIndexBuffer(6, BufferUsage.STREAM_DRAW, IndexDatatype.UNSIGNED_INT); + expect(buffer).toBeDefined(); + buffer.destroy(); + } else { + expect(function() { + context.createIndexBuffer(6, BufferUsage.STREAM_DRAW, IndexDatatype.UNSIGNED_INT); + }).toThrow(); + } + }); + it('gets the depth texture extension', function() { expect(context.getDepthTexture()).toBeDefined(); }); From 5bd91a782cc8957526990d5ad83a29085dc0bd6e Mon Sep 17 00:00:00 2001 From: hpinkos Date: Fri, 17 May 2013 14:34:22 -0400 Subject: [PATCH 035/306] added new test for computeNormal --- Source/Core/GeometryFilters.js | 12 ++++++------ Specs/Core/GeometryFiltersSpec.js | 24 ++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/Source/Core/GeometryFilters.js b/Source/Core/GeometryFilters.js index 5dacb8244b63..3fdf63020067 100644 --- a/Source/Core/GeometryFilters.js +++ b/Source/Core/GeometryFilters.js @@ -853,11 +853,9 @@ define([ }); }; - var normalsPerVertex = []; - var normalsPerTriangle = []; - var normalIndices = []; var p = new Cartesian3(); var q = new Cartesian3(); + var normal = new Cartesian3(); GeometryFilters.computeNormals = function(vertices, indices, result) { if (typeof vertices === 'undefined' || vertices.length < 0) { throw new DeveloperError('vertices is required to have a length greater than zero'); @@ -868,8 +866,10 @@ define([ if (indices.length % 3 !== 0) { throw new DeveloperError('length of indices must be a multiple of three'); } - normalsPerVertex.length = 0; - normalsPerTriangle.length = 0; + + var normalsPerVertex = []; + var normalsPerTriangle = []; + var normalIndices = []; var numVertices = vertices.length; var numIndices = indices.length; @@ -935,7 +935,7 @@ define([ for (i = 0; i < numVertices; i++) { vertexNormalData = normalsPerVertex[i]; if (vertexNormalData.count > 0) { - var normal = new Cartesian3(); + Cartesian3.ZERO.clone(normal); for (j = 0; j < vertexNormalData.count; j++) { normal.add(normalsPerTriangle[normalIndices[vertexNormalData.indexOffset + j]], normal); } diff --git a/Specs/Core/GeometryFiltersSpec.js b/Specs/Core/GeometryFiltersSpec.js index a8abde37e832..ffda01ce6553 100644 --- a/Specs/Core/GeometryFiltersSpec.js +++ b/Specs/Core/GeometryFiltersSpec.js @@ -643,4 +643,28 @@ defineSuite([ expect(results[3]).toEqual(new Cartesian3(1, 0, 1).normalize()); }); + it('GeometryFilters.computeNormals computes normal for six triangles', function() { + var vertices = []; + var indices = [0, 1, 2, 3, 0, 2, 4, 0, 3, 4, 5, 0, 5, 6, 0, 6, 1, 0]; + + vertices.push(Cartesian3.ZERO); + vertices.push(new Cartesian3(1,0,0)); + vertices.push(new Cartesian3(1,0,1)); + vertices.push(new Cartesian3(0,0,1)); + vertices.push(new Cartesian3(0,1,1)); + vertices.push(new Cartesian3(0,1,0)); + vertices.push(new Cartesian3(1,1,0)); + + var results = GeometryFilters.computeNormals(vertices, indices); + + expect(results.length).toEqual(7); + expect(results[0]).toEqual(new Cartesian3(-1, -1, -1).normalize()); + expect(results[1]).toEqual(new Cartesian3(0, -1, -1).normalize()); + expect(results[2]).toEqual(new Cartesian3(0, -1, 0).normalize()); + expect(results[3]).toEqual(new Cartesian3(-1, -1, 0).normalize()); + expect(results[4]).toEqual(new Cartesian3(-1, 0, 0).normalize()); + expect(results[5]).toEqual(new Cartesian3(-1, 0, -1).normalize()); + expect(results[6]).toEqual(new Cartesian3(0, 0, -1).normalize()); + }); + }); \ No newline at end of file From 84d68a88e42ee8f2ed8535afd807196f8786ec21 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Fri, 17 May 2013 16:43:13 -0400 Subject: [PATCH 036/306] Modify tangents and binormals to match the texture coordinate directions. --- Source/Core/BoxGeometry.js | 151 ++++++++++++++++++------------------- 1 file changed, 75 insertions(+), 76 deletions(-) diff --git a/Source/Core/BoxGeometry.js b/Source/Core/BoxGeometry.js index 45691c89cac9..f47f681df886 100644 --- a/Source/Core/BoxGeometry.js +++ b/Source/Core/BoxGeometry.js @@ -150,6 +150,50 @@ define([ }); } + if (vertexFormat.st) { + attributes.st = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 2, + values : [ + // +z face + 0.0, 0.0, + 1.0, 0.0, + 1.0, 1.0, + 0.0, 1.0, + + // -z face + 1.0, 0.0, + 0.0, 0.0, + 0.0, 1.0, + 1.0, 1.0, + + // +x face + 0.0, 0.0, + 1.0, 0.0, + 1.0, 1.0, + 0.0, 1.0, + + // -x face + 1.0, 0.0, + 0.0, 0.0, + 0.0, 1.0, + 1.0, 1.0, + + // +y face + 1.0, 0.0, + 0.0, 0.0, + 0.0, 1.0, + 1.0, 1.0, + + // -y face + 0.0, 0.0, + 1.0, 0.0, + 1.0, 1.0, + 0.0, 1.0 + ] + }); + } + if (vertexFormat.tangent) { attributes.tangent = new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, @@ -168,28 +212,28 @@ define([ -1.0, 0.0, 0.0, // +x face - 0.0, 0.0, -1.0, - 0.0, 0.0, -1.0, - 0.0, 0.0, -1.0, - 0.0, 0.0, -1.0, + 0.0, 1.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 1.0, 0.0, // -x face - 0.0, 0.0, 1.0, - 0.0, 0.0, 1.0, - 0.0, 0.0, 1.0, - 0.0, 0.0, 1.0, + 0.0, -1.0, 0.0, + 0.0, -1.0, 0.0, + 0.0, -1.0, 0.0, + 0.0, -1.0, 0.0, // +y face - 1.0, 0.0, 0.0, - 1.0, 0.0, 0.0, - 1.0, 0.0, 0.0, - 1.0, 0.0, 0.0, - - // -y face -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, - -1.0, 0.0, 0.0 + -1.0, 0.0, 0.0, + + // -y face + 1.0, 0.0, 0.0, + 1.0, 0.0, 0.0, + 1.0, 0.0, 0.0, + 1.0, 0.0, 0.0 ] }); } @@ -200,28 +244,28 @@ define([ componentsPerAttribute : 3, values : [ // +z face - 0.0, -1.0, 0.0, - 0.0, -1.0, 0.0, - 0.0, -1.0, 0.0, - 0.0, -1.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 1.0, 0.0, // -z face - 0.0, -1.0, 0.0, - 0.0, -1.0, 0.0, - 0.0, -1.0, 0.0, - 0.0, -1.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 1.0, 0.0, // +x face - 0.0, -1.0, 0.0, - 0.0, -1.0, 0.0, - 0.0, -1.0, 0.0, - 0.0, -1.0, 0.0, + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, // -x face - 0.0, -1.0, 0.0, - 0.0, -1.0, 0.0, - 0.0, -1.0, 0.0, - 0.0, -1.0, 0.0, + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, // +y face 0.0, 0.0, 1.0, @@ -238,51 +282,6 @@ define([ }); } - - if (vertexFormat.st) { - attributes.st = new GeometryAttribute({ - componentDatatype : ComponentDatatype.FLOAT, - componentsPerAttribute : 2, - values : [ - // +z face - 0.0, 0.0, - 1.0, 0.0, - 1.0, 1.0, - 0.0, 1.0, - - // -z face - 1.0, 0.0, - 0.0, 0.0, - 0.0, 1.0, - 1.0, 1.0, - - // +x face - 0.0, 0.0, - 1.0, 0.0, - 1.0, 1.0, - 0.0, 1.0, - - // -x face - 1.0, 0.0, - 0.0, 0.0, - 0.0, 1.0, - 1.0, 1.0, - - // +y face - 1.0, 0.0, - 0.0, 0.0, - 0.0, 1.0, - 1.0, 1.0, - - // -y face - 0.0, 0.0, - 1.0, 0.0, - 1.0, 1.0, - 0.0, 1.0 - ] - }); - } - indexLists.push( new GeometryIndices({ // 12 triangles: 6 faces, 2 triangles each. From 1986e7aa95d9742135a289b6adcaceb9a551f3f4 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Fri, 17 May 2013 17:17:18 -0400 Subject: [PATCH 037/306] Add czm_tangentToEyeSpaceMatrix built-in GLSL function. --- Source/Shaders/BuiltinFunctions.glsl | 26 ++++++++++++++++++++++ Source/Shaders/DefaultAppearanceAllFS.glsl | 11 ++------- Specs/Renderer/BuiltinFunctionsSpec.js | 13 +++++++++++ 3 files changed, 41 insertions(+), 9 deletions(-) diff --git a/Source/Shaders/BuiltinFunctions.glsl b/Source/Shaders/BuiltinFunctions.glsl index 55c9bbe2156d..bec911ca4c15 100644 --- a/Source/Shaders/BuiltinFunctions.glsl +++ b/Source/Shaders/BuiltinFunctions.glsl @@ -261,6 +261,32 @@ vec4 czm_windowToEyeCoordinates(vec4 fragmentCoordinate) return q; } +/** + * Creates a matrix that transforms vectors from tangent space to eye space. + * + * @name czm_tangentToEyeSpaceMatrix + * @glslFunction + * + * @param {vec3} normalEC The normal vector in eye coordinates. + * @param {vec3} tangentEC The tangent vector in eye coordinates. + * @param {vec3} binormalEC The binormal vector in eye coordinates. + * + * @returns {mat3} The matrix that transforms from tangent space to eye space. + * + * @example + * mat3 tangentToEye = czm_tangentToEyeSpaceMatrix(normalEC, tangentEC, binormalEC); + * vec3 normal = tangentToEye * texture2D(normalMap, st).xyz; + */ +mat3 czm_tangentToEyeSpaceMatrix(vec3 normalEC, vec3 tangentEC, vec3 binormalEC) +{ + vec3 normal = normalize(normalEC); + vec3 tangent = normalize(tangentEC); + vec3 binormal = normalize(binormalEC); + return mat3(tangent.x, tangent.y, tangent.z, + binormal.x, binormal.y, binormal.z, + normal.x, normal.y, normal.z); +} + /////////////////////////////////////////////////////////////////////////////// /** diff --git a/Source/Shaders/DefaultAppearanceAllFS.glsl b/Source/Shaders/DefaultAppearanceAllFS.glsl index 010f1ba4b81e..ef13534d7eff 100644 --- a/Source/Shaders/DefaultAppearanceAllFS.glsl +++ b/Source/Shaders/DefaultAppearanceAllFS.glsl @@ -7,17 +7,10 @@ varying vec2 v_st; void main() { vec3 positionToEyeEC = -v_positionEC; - - vec3 normalEC = normalize(v_normalEC); - vec3 tangentEC = normalize(v_tangentEC); - vec3 binormalEC = normalize(v_binormalEC); - mat3 tangentToEyeMatrix = mat3( - tangentEC.x, tangentEC.y, tangentEC.z, - binormalEC.x, binormalEC.y, binormalEC.z, - normalEC.x, normalEC.y, normalEC.z); + mat3 tangentToEyeMatrix = czm_tangentToEyeSpaceMatrix(v_normalEC, v_tangentEC, v_binormalEC); czm_materialInput materialInput; - materialInput.normalEC = normalEC; + materialInput.normalEC = normalize(v_normalEC); materialInput.tangentToEyeMatrix = tangentToEyeMatrix; materialInput.positionToEyeEC = positionToEyeEC; materialInput.st = v_st; diff --git a/Specs/Renderer/BuiltinFunctionsSpec.js b/Specs/Renderer/BuiltinFunctionsSpec.js index 59deef109879..912d9a5fd184 100644 --- a/Specs/Renderer/BuiltinFunctionsSpec.js +++ b/Specs/Renderer/BuiltinFunctionsSpec.js @@ -153,6 +153,19 @@ defineSuite([ verifyDraw(fs); }); + it('has czm_tangentToEyeSpaceMatrix', function() { + var fs = + 'void main() { ' + + ' vec3 tangent = vec3(1.0, 0.0, 0.0); ' + + ' vec3 binormal = vec3(0.0, 1.0, 0.0); ' + + ' vec3 normal = vec3(0.0, 0.0, 1.0); ' + + ' mat3 expected = mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0); ' + + ' mat3 actual = czm_tangentToEyeSpaceMatrix(normal, tangent, binormal); ' + + ' gl_FragColor = vec4(actual == expected); ' + + '}'; + verifyDraw(fs); + }); + it('has czm_translateRelativeToEye', function() { var camera = createCamera(context, new Cartesian3(1.0, 2.0, 3.0)); context.getUniformState().update(createFrameState(camera)); From 3288d99f72ca1e234756edb01ed6ec6810102ccd Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Fri, 17 May 2013 19:17:03 -0400 Subject: [PATCH 038/306] Add tests. --- Specs/Core/BoxGeometrySpec.js | 38 +++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/Specs/Core/BoxGeometrySpec.js b/Specs/Core/BoxGeometrySpec.js index 7605e6c69233..7cab060fd7dd 100644 --- a/Specs/Core/BoxGeometrySpec.js +++ b/Specs/Core/BoxGeometrySpec.js @@ -2,15 +2,17 @@ defineSuite([ 'Core/BoxGeometry', 'Core/VertexFormat', - 'Core/Cartesian3' + 'Core/Cartesian3', + 'Core/Matrix4' ], function( BoxGeometry, VertexFormat, - Cartesian3) { + Cartesian3, + Matrix4) { "use strict"; /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/ - it('compute0', function() { + it('constructor throws with negative dimanesions', function() { expect(function() { return new BoxGeometry({ dimensions : new Cartesian3(1, 2, -1) @@ -18,7 +20,7 @@ defineSuite([ }).toThrow(); }); - it('compute1', function() { + it('constructor creates optimized number of positions for VertexFormat.POSITIONS_ONLY', function() { var m = new BoxGeometry({ dimensions : new Cartesian3(1, 2, 3), vertexFormat : VertexFormat.POSITION_ONLY @@ -28,12 +30,26 @@ defineSuite([ expect(m.indexLists[0].values.length).toEqual(12 * 3); }); - it('compute2', function() { - expect(function() { - return new BoxGeometry({ - minimumCorner : new Cartesian3(0, 0, 0), - maximumCorner : new Cartesian3(1, 1, 1) - }); - }).not.toThrow(); + it('constructor computes all vertex attributes', function() { + var minimumCorner = new Cartesian3(0, 0, 0); + var maximumCorner = new Cartesian3(1, 1, 1); + var m = new BoxGeometry({ + minimumCorner : minimumCorner, + maximumCorner : maximumCorner, + vertexFormat : VertexFormat.ALL + }); + + expect(m.attributes.position.values.length).toEqual(6 * 4 * 3); + expect(m.attributes.normal.values.length).toEqual(6 * 4 * 3); + expect(m.attributes.tangent.values.length).toEqual(6 * 4 * 3); + expect(m.attributes.binormal.values.length).toEqual(6 * 4 * 3); + expect(m.attributes.st.values.length).toEqual(6 * 4 * 2); + + expect(m.indexLists[0].values.length).toEqual(12 * 3); + + expect(m.boundingSphere.center).toEqual(Cartesian3.ZERO); + expect(m.boundingSphere.radius).toEqual(maximumCorner.magnitude() * 0.5); + + expect(m.modelMatrix).toEqual(Matrix4.IDENTITY); }); }); \ No newline at end of file From 69ba6a4a80fb336d71add93b8e7fd07eab2f2c79 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Fri, 17 May 2013 19:39:54 -0400 Subject: [PATCH 039/306] Add doc. --- Source/Core/BoxGeometry.js | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/Source/Core/BoxGeometry.js b/Source/Core/BoxGeometry.js index f47f681df886..e2b586259ec2 100644 --- a/Source/Core/BoxGeometry.js +++ b/Source/Core/BoxGeometry.js @@ -24,11 +24,18 @@ define([ "use strict"; /** - * DOC_TBA + * Creates vertices and indices for a cube centered at the origin. * * @alias BoxGeometry * @constructor * + * @param {Cartesian3} [options.minimumCorner] The minimum x, y, and z coordinates of the box. + * @param {Cartesian3} [options.maximumCorner] The maximum x, y, and z coordinates of the box. + * @param {Cartesian3} [options.dimensions=new Cartesian3(1.0, 1.0, 1.0)] The width, depth, and height of the box stored in the x, y, and z coordinates of the Cartesian3, respectively. + * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed. + * @param {Matrix4} [options.modelMatrix] The model matrix for this box. See {@link czm_model}. + * @param {DOC_TBA} [options.pickData] DOC_TBA + * * @exception {DeveloperError} All dimensions components must be greater than or equal to zero. */ var BoxGeometry = function(options) { @@ -352,22 +359,38 @@ define([ } /** - * DOC_TBA + * An object containing {@link GeometryAttribute} properties named after each of the + * true values of the {@link VertexFormat} option. + * + * @type Object */ this.attributes = attributes; /** - * DOC_TBA + * An array of {@link GeometryIndices} defining primitives. + * + * @type Array */ this.indexLists = indexLists; /** - * DOC_TBA + * A tight-fitting bounding sphere that encloses the vertices of the box + * + * @type BoundingSphere */ this.boundingSphere = new BoundingSphere(new Cartesian3(), max.subtract(min).magnitude() * 0.5); /** - * DOC_TBA + * The 4x4 transformation matrix that transforms the box from model to world coordinates. + * When this is the identity matrix, the box is drawn in world coordinates, i.e., Earth's WGS84 coordinates. + * Local reference frames can be used by providing a different transformation matrix, like that returned + * by {@link Transforms.eastNorthUpToFixedFrame}. This matrix is available to GLSL vertex and fragment + * shaders via {@link czm_model} and derived uniforms. + * + * @type Matrix4 + * + * @see Transforms.eastNorthUpToFixedFrame + * @see czm_model */ this.modelMatrix = defaultValue(options.modelMatrix, Matrix4.IDENTITY.clone()); From 14e5f2ef75a37672fa5ab15b142e47c0c8679984 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Fri, 17 May 2013 19:42:23 -0400 Subject: [PATCH 040/306] Update CHANGES.md. --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index 375e4e593609..0be283e8b5ba 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -19,6 +19,7 @@ Beta Releases * Added `GeometryFilters.combine` to combine meshes for better batching. * Added `BoundingSphere.fromEllipsoid`. * Added renderer support for `OES_element_index_uint`, which can improve performance by reducing batch sizes. +* Added 'czm_tangentToEyeSpaceMatrix` built-in GLSL function. ### b17 - 2013-06-03 From afe00a6844dfc3641c7cd89401085c776d755f43 Mon Sep 17 00:00:00 2001 From: hpinkos Date: Mon, 20 May 2013 14:24:09 -0400 Subject: [PATCH 041/306] computeNormals takes mesh as a parameter added documentation --- CHANGES.md | 1 + Source/Core/GeometryFilters.js | 185 +++++++++++++++++------------- Specs/Core/GeometryFiltersSpec.js | 172 ++++++++++++++++++++------- 3 files changed, 237 insertions(+), 121 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index ca4e3e5ec903..14c79e4f88ce 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -18,6 +18,7 @@ Beta Releases * Improved the performance of drawing polygons created with `configureFromPolygonHierarchy`. * Added `GeometryFilters.combine` to combine meshes for better batching. * Added `BoundingSphere.fromEllipsoid`. +* Added `GeometryFilters.computeNormals` to find the normals of vertices in a mesh. ### b17 - 2013-06-03 diff --git a/Source/Core/GeometryFilters.js b/Source/Core/GeometryFilters.js index 3fdf63020067..f107096b10ba 100644 --- a/Source/Core/GeometryFilters.js +++ b/Source/Core/GeometryFilters.js @@ -853,99 +853,128 @@ define([ }); }; - var p = new Cartesian3(); - var q = new Cartesian3(); + /** + * Computes the normals of all vertices in a mesh based on the normals of triangles that include the vertex. + * + * @param {Geometry} mesh The mesh to filter, which is modified in place. + * @param {Object} mesh.attributes.position + * + * @returns The modified mesh argument. + * + * @exception {DeveloperError} mesh.attributes.position.values is required + * + * @example + * mesh = GeometryFilters.computeNormals(mesh); + * + */ + var pScratch = new Cartesian3(); + var qScratch = new Cartesian3(); var normal = new Cartesian3(); - GeometryFilters.computeNormals = function(vertices, indices, result) { - if (typeof vertices === 'undefined' || vertices.length < 0) { - throw new DeveloperError('vertices is required to have a length greater than zero'); - } - if (typeof indices === 'undefined' || indices.length < 2) { - throw new DeveloperError('indices is requred to have a length greater than two'); - } - if (indices.length % 3 !== 0) { - throw new DeveloperError('length of indices must be a multiple of three'); + GeometryFilters.computeNormals = function(mesh) { + if (typeof mesh === 'undefined') { + throw new DeveloperError('mesh is required.'); } - - var normalsPerVertex = []; - var normalsPerTriangle = []; - var normalIndices = []; - var numVertices = vertices.length; - var numIndices = indices.length; - - if (typeof result === 'undefined') { - result = []; + var attributes = mesh.attributes; + if (typeof mesh === 'undefined' || typeof attributes.position === 'undefined' || + typeof attributes.position.values === 'undefined' || typeof mesh.attributes.position.values === 'undefined') { + throw new DeveloperError('mesh.attributes.position.values is required'); } - - for (var i = 0; i < numVertices; i++) { - normalsPerVertex[i] = { - indexOffset: 0, - count: 0, - currentCount: 0 - }; + var vertices = mesh.attributes.position.values; + var indexLists = mesh.indexLists; + if (typeof indexLists === 'undefined') { + return mesh; } - var j = 0; - for (i = 0; i < numIndices; i+=3) { - var i0 = indices[i]; - var i1 = indices[i+1]; - var i2 = indices[i+2]; - - var v0 = vertices[i0]; - var v1 = vertices[i1]; - var v2 = vertices[i2]; - - normalsPerVertex[i0].count++; - normalsPerVertex[i1].count++; - normalsPerVertex[i2].count++; - - v1.subtract(v0, p); - v2.subtract(v1, q); - normalsPerTriangle[j] = p.cross(q); - j++; - } + var length = indexLists.length; + for (var k = 0; k < length; k++) { + var indices = indexLists[k].values; + if (indexLists[k].primitiveType !== PrimitiveType.TRIANGLES || typeof indices === 'undefined' || + indices.length < 2 || indices.length % 3 !== 0) { + continue; + } - var indexOffset = 0; - for (i = 0; i < numVertices; i++) { - normalsPerVertex[i].indexOffset += indexOffset; - indexOffset += normalsPerVertex[i].count; - } + var normalsPerVertex = []; + var normalsPerTriangle = []; + var normalIndices = []; + var numVertices = vertices.length; + var numIndices = indices.length; + + for (var i = 0; i < numVertices; i++) { + normalsPerVertex[i] = { + indexOffset: 0, + count: 0, + currentCount: 0 + }; + } - j = 0; - var vertexNormalData; - for (i = 0; i < numIndices; i+=3) { - vertexNormalData = normalsPerVertex[indices[i]]; - var index = vertexNormalData.indexOffset + vertexNormalData.currentCount; - normalIndices[index] = j; - vertexNormalData.currentCount++; + var j = 0; + for (i = 0; i < numIndices; i+=3) { + var i0 = indices[i]; + var i1 = indices[i+1]; + var i2 = indices[i+2]; + + var v0 = vertices[i0]; + var v1 = vertices[i1]; + var v2 = vertices[i2]; + + normalsPerVertex[i0].count++; + normalsPerVertex[i1].count++; + normalsPerVertex[i2].count++; + + v1.subtract(v0, pScratch); + v2.subtract(v1, qScratch); + normalsPerTriangle[j] = pScratch.cross(qScratch); + j++; + } - vertexNormalData = normalsPerVertex[indices[i+1]]; - index = vertexNormalData.indexOffset + vertexNormalData.currentCount; - normalIndices[index] = j; - vertexNormalData.currentCount++; + var indexOffset = 0; + for (i = 0; i < numVertices; i++) { + normalsPerVertex[i].indexOffset += indexOffset; + indexOffset += normalsPerVertex[i].count; + } - vertexNormalData = normalsPerVertex[indices[i+2]]; - index = vertexNormalData.indexOffset + vertexNormalData.currentCount; - normalIndices[index] = j; - vertexNormalData.currentCount++; + j = 0; + var vertexNormalData; + for (i = 0; i < numIndices; i+=3) { + vertexNormalData = normalsPerVertex[indices[i]]; + var index = vertexNormalData.indexOffset + vertexNormalData.currentCount; + normalIndices[index] = j; + vertexNormalData.currentCount++; + + vertexNormalData = normalsPerVertex[indices[i+1]]; + index = vertexNormalData.indexOffset + vertexNormalData.currentCount; + normalIndices[index] = j; + vertexNormalData.currentCount++; + + vertexNormalData = normalsPerVertex[indices[i+2]]; + index = vertexNormalData.indexOffset + vertexNormalData.currentCount; + normalIndices[index] = j; + vertexNormalData.currentCount++; + + j++; + } - j++; - } + for (i = 0; i < numVertices; i++) { + vertexNormalData = normalsPerVertex[i]; + if (typeof mesh.attributes.normal === 'undefined') { + mesh.attributes.normal = { + values: [] + }; + } - for (i = 0; i < numVertices; i++) { - vertexNormalData = normalsPerVertex[i]; - if (vertexNormalData.count > 0) { - Cartesian3.ZERO.clone(normal); - for (j = 0; j < vertexNormalData.count; j++) { - normal.add(normalsPerTriangle[normalIndices[vertexNormalData.indexOffset + j]], normal); + if (vertexNormalData.count > 0) { + Cartesian3.ZERO.clone(normal); + for (j = 0; j < vertexNormalData.count; j++) { + normal.add(normalsPerTriangle[normalIndices[vertexNormalData.indexOffset + j]], normal); + } + mesh.attributes.normal.values[i] = normal.normalize(); + } else { + mesh.attributes.normal.values[i] = Cartesian3.UNIT_Z.clone(); } - result[i] = normal.normalize(); - } else { - result[i] = Cartesian3.UNIT_Z; } } - return result; + return mesh; }; return GeometryFilters; diff --git a/Specs/Core/GeometryFiltersSpec.js b/Specs/Core/GeometryFiltersSpec.js index ffda01ce6553..2c2308ec43a3 100644 --- a/Specs/Core/GeometryFiltersSpec.js +++ b/Specs/Core/GeometryFiltersSpec.js @@ -608,63 +608,149 @@ defineSuite([ }).toThrow(); }); + it('GeometryFilters.computeNormals throws when mesh is undefined', function() { + expect(function() { + GeometryFilters.computeNormals(); + }).toThrow(); + }); - it('GeometryFilters.computeNormals computes normal for one triangle', function() { - var vertices = []; - var indices = [0, 1, 2]; + it('GeometryFilters.computeNormals throws when mesh.attributes is undefined', function() { + expect(function() { + GeometryFilters.computeNormals(new Geometry()); + }).toThrow(); + }); - vertices.push(Cartesian3.ZERO); - vertices.push(Cartesian3.UNIT_X); - vertices.push(Cartesian3.UNIT_Y); + it('GeometryFilters.computeNormals throws when mesh.attributes.position is undefined', function() { + expect(function() { + GeometryFilters.computeNormals(new Geometry( { + attributes: {} + })); + }).toThrow(); + }); - var results = GeometryFilters.computeNormals(vertices, indices); + it('GeometryFilters.computeNormals throws when mesh.attributes.position.values is undefined', function() { + expect(function() { + GeometryFilters.computeNormals(new Geometry( { + attributes: { + position: {} + } + })); + }).toThrow(); + }); - expect(results.length).toEqual(3); - expect(results[0]).toEqual(Cartesian3.UNIT_Z); - expect(results[1]).toEqual(Cartesian3.UNIT_Z); - expect(results[2]).toEqual(Cartesian3.UNIT_Z); + it('GeometryFilters.computeNormals does not compute normals when mesh.indexLists is undefined', function() { + var mesh = new Geometry({ + attributes: { + position: { + values: [Cartesian3.ZERO, Cartesian3.UNIT_X, Cartesian3.UNIT_Y] + } + } + }); + + mesh = GeometryFilters.computeNormals(mesh); + + expect(typeof mesh.attributes.normal === 'undefined').toEqual(true); }); - it('GeometryFilters.computeNormals computes normal for two triangles', function() { - var vertices = []; - var indices = [0, 1, 2, 1, 3, 2]; + it('GeometryFilters.computeNormals does not compute normals when mesh.indexLists is undefined', function() { + var mesh = new Geometry({ + attributes: { + position: { + values: [Cartesian3.ZERO, Cartesian3.UNIT_X, Cartesian3.UNIT_Y] + } + } + }); + + mesh = GeometryFilters.computeNormals(mesh); - vertices.push(Cartesian3.ZERO); - vertices.push(new Cartesian3(1,0,1)); - vertices.push(new Cartesian3(1,1,1)); - vertices.push(new Cartesian3(2,0,0)); + expect(typeof mesh.attributes.normal === 'undefined').toEqual(true); + }); + + it('GeometryFilters.computeNormals does not compute normals when primitive type is not triangle', function() { + var mesh = new Geometry({ + attributes: { + position: { + values: [Cartesian3.ZERO, Cartesian3.UNIT_X, Cartesian3.UNIT_Y] + } + }, + indexLists: [{ + primitiveType: PrimitiveType.TRIANGLE_STRIP, + values: [0, 1, 2] + }] + }); - var results = GeometryFilters.computeNormals(vertices, indices); + mesh = GeometryFilters.computeNormals(mesh); - expect(results.length).toEqual(4); - expect(results[0]).toEqual(new Cartesian3(-1, 0, 1).normalize()); - expect(results[1]).toEqual(Cartesian3.UNIT_Z); - expect(results[2]).toEqual(Cartesian3.UNIT_Z); - expect(results[3]).toEqual(new Cartesian3(1, 0, 1).normalize()); + expect(typeof mesh.attributes.normal === 'undefined').toEqual(true); }); - it('GeometryFilters.computeNormals computes normal for six triangles', function() { - var vertices = []; - var indices = [0, 1, 2, 3, 0, 2, 4, 0, 3, 4, 5, 0, 5, 6, 0, 6, 1, 0]; - vertices.push(Cartesian3.ZERO); - vertices.push(new Cartesian3(1,0,0)); - vertices.push(new Cartesian3(1,0,1)); - vertices.push(new Cartesian3(0,0,1)); - vertices.push(new Cartesian3(0,1,1)); - vertices.push(new Cartesian3(0,1,0)); - vertices.push(new Cartesian3(1,1,0)); + it('GeometryFilters.computeNormals computes normal for one triangle', function() { + var mesh = new Geometry({ + attributes: { + position: { + values: [Cartesian3.ZERO, Cartesian3.UNIT_X, Cartesian3.UNIT_Y] + } + }, + indexLists: [{ + primitiveType: PrimitiveType.TRIANGLES, + values: [0, 1, 2] + }] + }); - var results = GeometryFilters.computeNormals(vertices, indices); + mesh = GeometryFilters.computeNormals(mesh); - expect(results.length).toEqual(7); - expect(results[0]).toEqual(new Cartesian3(-1, -1, -1).normalize()); - expect(results[1]).toEqual(new Cartesian3(0, -1, -1).normalize()); - expect(results[2]).toEqual(new Cartesian3(0, -1, 0).normalize()); - expect(results[3]).toEqual(new Cartesian3(-1, -1, 0).normalize()); - expect(results[4]).toEqual(new Cartesian3(-1, 0, 0).normalize()); - expect(results[5]).toEqual(new Cartesian3(-1, 0, -1).normalize()); - expect(results[6]).toEqual(new Cartesian3(0, 0, -1).normalize()); + expect(mesh.attributes.normal.values.length).toEqual(3); + expect(mesh.attributes.normal.values[0]).toEqual(Cartesian3.UNIT_Z); + expect(mesh.attributes.normal.values[1]).toEqual(Cartesian3.UNIT_Z); + expect(mesh.attributes.normal.values[2]).toEqual(Cartesian3.UNIT_Z); }); + it('GeometryFilters.computeNormals computes normal for two triangles', function() { + var mesh = new Geometry({ + attributes: { + position: { + values: [Cartesian3.ZERO, new Cartesian3(1,0,1), new Cartesian3(1,1,1), new Cartesian3(2,0,0)] + } + }, + indexLists: [{ + primitiveType: PrimitiveType.TRIANGLES, + values: [0, 1, 2, 1, 3, 2] + }] + }); + + mesh = GeometryFilters.computeNormals(mesh); + + expect(mesh.attributes.normal.values.length).toEqual(4); + expect(mesh.attributes.normal.values[0]).toEqual(new Cartesian3(-1, 0, 1).normalize()); + expect(mesh.attributes.normal.values[1]).toEqual(Cartesian3.UNIT_Z); + expect(mesh.attributes.normal.values[2]).toEqual(Cartesian3.UNIT_Z); + expect(mesh.attributes.normal.values[3]).toEqual(new Cartesian3(1, 0, 1).normalize()); + }); + + it('GeometryFilters.computeNormals computes normal for six triangles', function() { + var mesh = new Geometry ({ + attributes: { + position: { + values: [Cartesian3.ZERO, new Cartesian3(1,0,0), new Cartesian3(1,0,1), new Cartesian3(0,0,1), + new Cartesian3(0,1,1), new Cartesian3(0,1,0), new Cartesian3(1,1,0)] + } + }, + indexLists: [{ + primitiveType: PrimitiveType.TRIANGLES, + values: [0, 1, 2, 3, 0, 2, 4, 0, 3, 4, 5, 0, 5, 6, 0, 6, 1, 0] + }] + }); + + mesh = GeometryFilters.computeNormals(mesh); + + expect(mesh.attributes.normal.values.length).toEqual(7); + expect(mesh.attributes.normal.values[0]).toEqual(new Cartesian3(-1, -1, -1).normalize()); + expect(mesh.attributes.normal.values[1]).toEqual(new Cartesian3(0, -1, -1).normalize()); + expect(mesh.attributes.normal.values[2]).toEqual(new Cartesian3(0, -1, 0).normalize()); + expect(mesh.attributes.normal.values[3]).toEqual(new Cartesian3(-1, -1, 0).normalize()); + expect(mesh.attributes.normal.values[4]).toEqual(new Cartesian3(-1, 0, 0).normalize()); + expect(mesh.attributes.normal.values[5]).toEqual(new Cartesian3(-1, 0, -1).normalize()); + expect(mesh.attributes.normal.values[6]).toEqual(new Cartesian3(0, 0, -1).normalize()); + }); }); \ No newline at end of file From 9615e3c32bb024fcdbcfad0773547cf9974b0e59 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 20 May 2013 14:33:02 -0400 Subject: [PATCH 042/306] Update doc. --- Source/Core/BoxGeometry.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/Source/Core/BoxGeometry.js b/Source/Core/BoxGeometry.js index e2b586259ec2..3643ba3cc79e 100644 --- a/Source/Core/BoxGeometry.js +++ b/Source/Core/BoxGeometry.js @@ -37,6 +37,13 @@ define([ * @param {DOC_TBA} [options.pickData] DOC_TBA * * @exception {DeveloperError} All dimensions components must be greater than or equal to zero. + * + * @example + * var box = new BoxGeometry({ + * vertexFormat : VertexFormat.POSITION_ONLY, + * dimensions : new Cartesian3(500000.0, 500000.0, 500000.0), + * modelMatrix : Transforms.eastNorthUpToFixedFrame(center) + * }); */ var BoxGeometry = function(options) { options = defaultValue(options, defaultValue.EMPTY_OBJECT); @@ -381,16 +388,14 @@ define([ this.boundingSphere = new BoundingSphere(new Cartesian3(), max.subtract(min).magnitude() * 0.5); /** - * The 4x4 transformation matrix that transforms the box from model to world coordinates. - * When this is the identity matrix, the box is drawn in world coordinates, i.e., Earth's WGS84 coordinates. + * The 4x4 transformation matrix that transforms the geometry from model to world coordinates. + * When this is the identity matrix, the geometry is drawn in world coordinates, i.e., Earth's WGS84 coordinates. * Local reference frames can be used by providing a different transformation matrix, like that returned - * by {@link Transforms.eastNorthUpToFixedFrame}. This matrix is available to GLSL vertex and fragment - * shaders via {@link czm_model} and derived uniforms. + * by {@link Transforms.eastNorthUpToFixedFrame}. * * @type Matrix4 * * @see Transforms.eastNorthUpToFixedFrame - * @see czm_model */ this.modelMatrix = defaultValue(options.modelMatrix, Matrix4.IDENTITY.clone()); From d204b7dddb2b764581c54f4c4ada02e0de0f028d Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 20 May 2013 15:16:36 -0400 Subject: [PATCH 043/306] Add default values for undefined vertex attributes. --- Apps/CesiumViewer/CesiumViewer.js | 6 -- Source/Scene/Primitive.js | 89 ++++++++++++++++++++-- Source/Shaders/DefaultAppearanceAllFS.glsl | 23 ------ Source/Shaders/DefaultAppearanceAllVS.glsl | 28 ------- Source/Shaders/DefaultAppearanceFS.glsl | 11 ++- Source/Shaders/DefaultAppearanceVS.glsl | 6 ++ 6 files changed, 99 insertions(+), 64 deletions(-) delete mode 100644 Source/Shaders/DefaultAppearanceAllFS.glsl delete mode 100644 Source/Shaders/DefaultAppearanceAllVS.glsl diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index 66902962871b..1131ccc937ca 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -22,8 +22,6 @@ define([ 'Scene/Primitive', 'Scene/Appearance', 'Scene/Material', - 'Shaders/DefaultAppearanceAllFS', - 'Shaders/DefaultAppearanceAllVS', 'Widgets/Dojo/checkForChromeFrame', 'Widgets/Dojo/CesiumViewerWidget' ], function( @@ -49,8 +47,6 @@ define([ Primitive, Appearance, Material, - DefaultAppearanceAllFS, - DefaultAppearanceAllVS, checkForChromeFrame, CesiumViewerWidget) { "use strict"; @@ -138,8 +134,6 @@ define([ }; var appearance = new Appearance({ material : m, - vertexShaderSource : DefaultAppearanceAllVS, - fragmentShaderSource : DefaultAppearanceAllFS, renderState : rs }); diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index d06adb05176f..435e38bd7881 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -80,9 +80,8 @@ define([ function addPickColorAttribute(primitive, geometries, context) { var length = geometries.length; - var i; - for (i = 0; i < length; ++i) { + for (var i = 0; i < length; ++i) { var geometry = geometries[i]; var attributes = geometry.attributes; var positionAttr = attributes.position; @@ -119,6 +118,83 @@ define([ } } + function addDefaultAttributes(geometries) { + var length = geometries.length; + for (var i = 0; i < length; ++i) { + var geometry = geometries[i]; + var attributes = geometry.attributes; + var positionAttr = attributes.position; + var positionLength = positionAttr.values.length / positionAttr.componentsPerAttribute; + + var numberOfComponents; + var values; + var j; + + if (typeof attributes.normal === 'undefined') { + numberOfComponents = 3 * positionLength; + values = new Float32Array(numberOfComponents); + attributes.normal = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : values + }); + + for (j = 0; j < numberOfComponents; j += 3) { + values[j] = 0.0; + values[j + 1] = 0.0; + values[j + 2] = 1.0; + } + } + + if (typeof attributes.tangent === 'undefined') { + numberOfComponents = 3 * positionLength; + values = new Float32Array(numberOfComponents); + attributes.tangent = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : values + }); + + for (j = 0; j < numberOfComponents; j += 3) { + values[j] = 1.0; + values[j + 1] = 0.0; + values[j + 2] = 0.0; + } + } + + if (typeof attributes.binormal === 'undefined') { + numberOfComponents = 3 * positionLength; + values = new Float32Array(numberOfComponents); + attributes.binormal = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : values + }); + + for (j = 0; j < numberOfComponents; j += 3) { + values[j] = 0.0; + values[j + 1] = 1.0; + values[j + 2] = 0.0; + } + } + + if (typeof attributes.st === 'undefined') { + numberOfComponents = 2 * positionLength; + values = new Float32Array(numberOfComponents); + attributes.st = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 2, + values : values + }); + + for (j = 0; j < numberOfComponents; j += 2) { + values[j] = 0.0; + values[j + 1] = 0.0; + } + } + } + } + function transformToWorldCoordinates(primitive, geometries) { var toWorld = primitive._transformToWorldCoordinates; var length = geometries.length; @@ -151,6 +227,9 @@ define([ addPickColorAttribute(primitive, geometries, context); } + // Add default values for any undefined attributes + addDefaultAttributes(geometries); + // Unify to world coordinates before combining. If there is only one geometry or all // geometries are in the same (non-world) coordinate system, only combine if the user requested it. transformToWorldCoordinates(primitive, geometries); @@ -270,7 +349,7 @@ define([ // The geometry is static but the model matrix can change if (frameState.passes.color || frameState.passes.pick) { length = colorCommands.length; - for (var i = 0; i < length; ++i) { + for (i = 0; i < length; ++i) { colorCommands[i].modelMatrix = this.modelMatrix; pickCommands[i].modelMatrix = this.modelMatrix; } @@ -303,12 +382,12 @@ define([ } this._va = undefined; - var pickIds = this_pickIds; + var pickIds = this._pickIds; length = pickIds.length; for (i = 0; i < length; ++i) { pickIds[i].destroy(); } - this.this_pickIds = undefined; + this._pickIds = undefined; return destroyObject(this); }; diff --git a/Source/Shaders/DefaultAppearanceAllFS.glsl b/Source/Shaders/DefaultAppearanceAllFS.glsl deleted file mode 100644 index ef13534d7eff..000000000000 --- a/Source/Shaders/DefaultAppearanceAllFS.glsl +++ /dev/null @@ -1,23 +0,0 @@ -varying vec3 v_normalEC; -varying vec3 v_tangentEC; -varying vec3 v_binormalEC; -varying vec3 v_positionEC; -varying vec2 v_st; - -void main() -{ - vec3 positionToEyeEC = -v_positionEC; - mat3 tangentToEyeMatrix = czm_tangentToEyeSpaceMatrix(v_normalEC, v_tangentEC, v_binormalEC); - - czm_materialInput materialInput; - materialInput.normalEC = normalize(v_normalEC); - materialInput.tangentToEyeMatrix = tangentToEyeMatrix; - materialInput.positionToEyeEC = positionToEyeEC; - materialInput.st = v_st; - czm_material material = czm_getMaterial(materialInput); - - //material.specular = 0.2; - //material.shininess = 10.0; - - gl_FragColor = czm_phong(normalize(positionToEyeEC), material); -} diff --git a/Source/Shaders/DefaultAppearanceAllVS.glsl b/Source/Shaders/DefaultAppearanceAllVS.glsl deleted file mode 100644 index 75b2321ba248..000000000000 --- a/Source/Shaders/DefaultAppearanceAllVS.glsl +++ /dev/null @@ -1,28 +0,0 @@ -attribute vec3 positionHigh; -attribute vec3 positionLow; -attribute vec3 normal; -attribute vec3 tangent; -attribute vec3 binormal; -attribute vec2 st; -attribute vec4 pickColor; - -varying vec3 v_normalEC; -varying vec3 v_tangentEC; -varying vec3 v_binormalEC; -varying vec3 v_positionEC; -varying vec2 v_st; -varying vec4 czm_pickColor; - -void main() -{ - vec4 p = czm_translateRelativeToEye(positionHigh, positionLow); - - v_normalEC = czm_normal * normal; // normal in eye coordinates - v_tangentEC = czm_normal * tangent; // tangent in eye coordinates - v_binormalEC = czm_normal * binormal; // binormal in eye coordinates - v_positionEC = (czm_modelViewRelativeToEye * p).xyz; // position in eye coordinates - v_st = st; - czm_pickColor = pickColor; - - gl_Position = czm_modelViewProjectionRelativeToEye * p; -} diff --git a/Source/Shaders/DefaultAppearanceFS.glsl b/Source/Shaders/DefaultAppearanceFS.glsl index 346f8e3334b3..fa05750ce982 100644 --- a/Source/Shaders/DefaultAppearanceFS.glsl +++ b/Source/Shaders/DefaultAppearanceFS.glsl @@ -1,17 +1,24 @@ varying vec3 v_normalEC; +varying vec3 v_tangentEC; +varying vec3 v_binormalEC; varying vec3 v_positionEC; varying vec2 v_st; void main() { vec3 positionToEyeEC = -v_positionEC; + mat3 tangentToEyeMatrix = czm_tangentToEyeSpaceMatrix(v_normalEC, v_tangentEC, v_binormalEC); czm_materialInput materialInput; - materialInput.normalEC = v_normalEC; + materialInput.normalEC = normalize(v_normalEC); + materialInput.tangentToEyeMatrix = tangentToEyeMatrix; materialInput.positionToEyeEC = positionToEyeEC; materialInput.st = v_st; czm_material material = czm_getMaterial(materialInput); -// gl_FragColor = czm_phong(normalize(positionToEyeEC), material); + //material.specular = 0.2; + //material.shininess = 10.0; + + //gl_FragColor = czm_phong(normalize(positionToEyeEC), material); gl_FragColor = vec4(material.diffuse + material.emission, material.alpha); } diff --git a/Source/Shaders/DefaultAppearanceVS.glsl b/Source/Shaders/DefaultAppearanceVS.glsl index 0a851ed9fa4f..75b2321ba248 100644 --- a/Source/Shaders/DefaultAppearanceVS.glsl +++ b/Source/Shaders/DefaultAppearanceVS.glsl @@ -1,10 +1,14 @@ attribute vec3 positionHigh; attribute vec3 positionLow; attribute vec3 normal; +attribute vec3 tangent; +attribute vec3 binormal; attribute vec2 st; attribute vec4 pickColor; varying vec3 v_normalEC; +varying vec3 v_tangentEC; +varying vec3 v_binormalEC; varying vec3 v_positionEC; varying vec2 v_st; varying vec4 czm_pickColor; @@ -14,6 +18,8 @@ void main() vec4 p = czm_translateRelativeToEye(positionHigh, positionLow); v_normalEC = czm_normal * normal; // normal in eye coordinates + v_tangentEC = czm_normal * tangent; // tangent in eye coordinates + v_binormalEC = czm_normal * binormal; // binormal in eye coordinates v_positionEC = (czm_modelViewRelativeToEye * p).xyz; // position in eye coordinates v_st = st; czm_pickColor = pickColor; From 41caa5200b2fb5e3f1f8aef6dc669204e2c5f863 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 20 May 2013 18:03:18 -0400 Subject: [PATCH 044/306] Add texture coordinates to ellipsoid geometry. --- Source/Core/EllipsoidGeometry.js | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/Source/Core/EllipsoidGeometry.js b/Source/Core/EllipsoidGeometry.js index 9c07a57f6a72..2d97246a7494 100644 --- a/Source/Core/EllipsoidGeometry.js +++ b/Source/Core/EllipsoidGeometry.js @@ -3,6 +3,7 @@ define([ './defaultValue', './DeveloperError', './Cartesian3', + './Math', './Matrix4', './Ellipsoid', './ComponentDatatype', @@ -15,6 +16,7 @@ define([ defaultValue, DeveloperError, Cartesian3, + CesiumMath, Matrix4, Ellipsoid, ComponentDatatype, @@ -134,6 +136,27 @@ define([ }); } + if (vertexFormat.st) { + var texCoords = new Array(length * 2); + var oneOverRadii = ellipsoid.getOneOverRadii(); + var sphericalNormal = new Cartesian3(); + + j = 0; + for (i = 0; i < length; ++i) { + Cartesian3.multiplyComponents(positions[i], oneOverRadii, sphericalNormal); + Cartesian3.normalize(sphericalNormal, sphericalNormal); + + texCoords[j++] = Math.atan2(sphericalNormal.y, sphericalNormal.x) * CesiumMath.ONE_OVER_TWO_PI + 0.5; + texCoords[j++] = Math.asin(sphericalNormal.z) * CesiumMath.ONE_OVER_PI + 0.5; + } + + attributes.st = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 2, + values : texCoords + }); + } + if (vertexFormat.normal) { var normals = new Array(length * 3); var normal = new Cartesian3(); From f6fb8b2078913e3b1e0aeafad2cfd6f6b6c71fbb Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 20 May 2013 19:19:35 -0400 Subject: [PATCH 045/306] Add normals and binormals to ellipsoid geometry. --- Apps/CesiumViewer/CesiumViewer.js | 6 +-- Source/Core/EllipsoidGeometry.js | 62 +++++++++++++++++++++++-------- 2 files changed, 50 insertions(+), 18 deletions(-) diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index 1131ccc937ca..f81fb7c19f54 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -137,11 +137,11 @@ define([ renderState : rs }); - var mesh4 = new BoxGeometry({ + var mesh4 = new EllipsoidGeometry({ vertexFormat : VertexFormat.ALL, - dimensions : new Cartesian3(1000000.0, 1000000.0, 1000000.0), + ellipsoid : new Ellipsoid(1000000.0, 500000.0, 500000.0), modelMatrix : Matrix4.multiplyByTranslation(Transforms.eastNorthUpToFixedFrame( - Ellipsoid.WGS84.cartographicToCartesian(Cartographic.fromDegrees(-75.59777, 40.03883))), new Cartesian3(0.0, 0.0, 4500000.0)), + Ellipsoid.WGS84.cartographicToCartesian(Cartographic.fromDegrees(-75.59777, 40.03883))), new Cartesian3(0.0, 0.0, 4500000.0)), pickData : 'mesh4' }); diff --git a/Source/Core/EllipsoidGeometry.js b/Source/Core/EllipsoidGeometry.js index 2d97246a7494..5d627b5b8952 100644 --- a/Source/Core/EllipsoidGeometry.js +++ b/Source/Core/EllipsoidGeometry.js @@ -119,11 +119,11 @@ define([ var radii = ellipsoid.getRadii(); var flattenedPositions = new Array(length * 3); - j = 0; - for (i = 0; i < length; ++i) { + for (i = j = 0; i < length; ++i) { var item = positions[i]; Cartesian3.normalize(item, item); Cartesian3.multiplyComponents(item, radii, item); + flattenedPositions[j++] = item.x; flattenedPositions[j++] = item.y; flattenedPositions[j++] = item.z; @@ -141,8 +141,7 @@ define([ var oneOverRadii = ellipsoid.getOneOverRadii(); var sphericalNormal = new Cartesian3(); - j = 0; - for (i = 0; i < length; ++i) { + for (i = j = 0; i < length; ++i) { Cartesian3.multiplyComponents(positions[i], oneOverRadii, sphericalNormal); Cartesian3.normalize(sphericalNormal, sphericalNormal); @@ -157,23 +156,56 @@ define([ }); } - if (vertexFormat.normal) { + if (vertexFormat.normal || vertexFormat.tangent || vertexFormat.binormal) { var normals = new Array(length * 3); + var tangents = new Array(length * 3); + var binormals = new Array(length * 3); + var normal = new Cartesian3(); + var tangent = new Cartesian3(); + var binormal = new Cartesian3(); - j = 0; - for (i = 0; i < length; ++i) { + for (i = j = 0; i < length; ++i, j += 3) { ellipsoid.geodeticSurfaceNormal(positions[i], normal); - normals[j++] = normal.x; - normals[j++] = normal.y; - normals[j++] = normal.z; + Cartesian3.cross(Cartesian3.UNIT_Z, normal, tangent); + Cartesian3.cross(normal, tangent, binormal); + + normals[j] = normal.x; + normals[j + 1] = normal.y; + normals[j + 2] = normal.z; + + tangents[j] = tangent.x; + tangents[j + 1] = tangent.y; + tangents[j + 2] = tangent.z; + + binormals[j] = binormal.x; + binormals[j + 1] = binormal.y; + binormals[j + 2] = binormal.z; } - attributes.normal = new GeometryAttribute({ - componentDatatype : ComponentDatatype.FLOAT, - componentsPerAttribute : 3, - values : normals - }); + if (vertexFormat.normal) { + attributes.normal = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : normals + }); + } + + if (vertexFormat.tangent) { + attributes.tangent = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : tangents + }); + } + + if (vertexFormat.binormal) { + attributes.binormal = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : binormals + }); + } } /** From 68bce522c95071b9c8836ae974a87d9072fe477d Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 20 May 2013 19:52:55 -0400 Subject: [PATCH 046/306] Update doc and remove some memory allocations. --- Source/Core/BoxGeometry.js | 4 +- Source/Core/EllipsoidGeometry.js | 72 ++++++++++++++++++++++++-------- 2 files changed, 57 insertions(+), 19 deletions(-) diff --git a/Source/Core/BoxGeometry.js b/Source/Core/BoxGeometry.js index 3643ba3cc79e..3970db8d2609 100644 --- a/Source/Core/BoxGeometry.js +++ b/Source/Core/BoxGeometry.js @@ -33,7 +33,7 @@ define([ * @param {Cartesian3} [options.maximumCorner] The maximum x, y, and z coordinates of the box. * @param {Cartesian3} [options.dimensions=new Cartesian3(1.0, 1.0, 1.0)] The width, depth, and height of the box stored in the x, y, and z coordinates of the Cartesian3, respectively. * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed. - * @param {Matrix4} [options.modelMatrix] The model matrix for this box. See {@link czm_model}. + * @param {Matrix4} [options.modelMatrix] The model matrix for this box. * @param {DOC_TBA} [options.pickData] DOC_TBA * * @exception {DeveloperError} All dimensions components must be greater than or equal to zero. @@ -381,7 +381,7 @@ define([ this.indexLists = indexLists; /** - * A tight-fitting bounding sphere that encloses the vertices of the box + * A tight-fitting bounding sphere that encloses the vertices of the geometry. * * @type BoundingSphere */ diff --git a/Source/Core/EllipsoidGeometry.js b/Source/Core/EllipsoidGeometry.js index 5d627b5b8952..443ead6eaf66 100644 --- a/Source/Core/EllipsoidGeometry.js +++ b/Source/Core/EllipsoidGeometry.js @@ -27,13 +27,31 @@ define([ VertexFormat) { "use strict"; + var sphericalNormal = new Cartesian3(); + var normal = new Cartesian3(); + var tangent = new Cartesian3(); + var binormal = new Cartesian3(); + /** - * DOC_TBA + * Creates vertices and indices for an ellipsoid centered at the origin. * * @alias EllipsoidGeometry * @constructor * + * @param {Ellipsoid} [options.ellipsoi=Ellipsoid.UNIT_SPHERE] The ellipsoid used to create vertex attributes. + * @param {Number} [options.numberOfPartitions=32] The number of times to partition the ellipsoid in a plane formed by two radii in a single quadrant. + * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed. + * @param {Matrix4} [options.modelMatrix] The model matrix for this ellipsoid. + * @param {DOC_TBA} [options.pickData] DOC_TBA + * * @exception {DeveloperError} options.numberOfPartitions must be greater than zero. + * + * @example + * var ellipsoid = new EllipsoidGeometry({ + * vertexFormat : VertexFormat.POSITION_ONLY, + * ellipsoid : new Ellipsoid(1000000.0, 500000.0, 500000.0), + * modelMatrix : Transforms.eastNorthUpToFixedFrame(center) + * }); */ var EllipsoidGeometry = function(options) { options = defaultValue(options, defaultValue.EMPTY_OBJECT); @@ -139,7 +157,6 @@ define([ if (vertexFormat.st) { var texCoords = new Array(length * 2); var oneOverRadii = ellipsoid.getOneOverRadii(); - var sphericalNormal = new Cartesian3(); for (i = j = 0; i < length; ++i) { Cartesian3.multiplyComponents(positions[i], oneOverRadii, sphericalNormal); @@ -161,10 +178,6 @@ define([ var tangents = new Array(length * 3); var binormals = new Array(length * 3); - var normal = new Cartesian3(); - var tangent = new Cartesian3(); - var binormal = new Cartesian3(); - for (i = j = 0; i < length; ++i, j += 3) { ellipsoid.geodeticSurfaceNormal(positions[i], normal); Cartesian3.cross(Cartesian3.UNIT_Z, normal, tangent); @@ -209,12 +222,17 @@ define([ } /** - * DOC_TBA + * An object containing {@link GeometryAttribute} properties named after each of the + * true values of the {@link VertexFormat} option. + * + * @type Object */ this.attributes = attributes; /** - * DOC_TBA + * An array of {@link GeometryIndices} defining primitives. + * + * @type Array */ this.indexLists = [ new GeometryIndices({ @@ -224,12 +242,21 @@ define([ ]; /** - * DOC_TBA + * A tight-fitting bounding sphere that encloses the vertices of the geometry. + * + * @type BoundingSphere */ this.boundingSphere = BoundingSphere.fromEllipsoid(ellipsoid); /** - * DOC_TBA + * The 4x4 transformation matrix that transforms the geometry from model to world coordinates. + * When this is the identity matrix, the geometry is drawn in world coordinates, i.e., Earth's WGS84 coordinates. + * Local reference frames can be used by providing a different transformation matrix, like that returned + * by {@link Transforms.eastNorthUpToFixedFrame}. + * + * @type Matrix4 + * + * @see Transforms.eastNorthUpToFixedFrame */ this.modelMatrix = defaultValue(options.modelMatrix, Matrix4.IDENTITY.clone()); @@ -239,28 +266,37 @@ define([ this.pickData = options.pickData; }; + var scratchDirection = new Cartesian3(); + function addEdgePositions(i0, i1, numberOfPartitions, positions) { var indices = []; indices[0] = i0; indices[2 + (numberOfPartitions - 1) - 1] = i1; var origin = positions[i0]; - var direction = positions[i1].subtract(positions[i0]); + var direction = Cartesian3.subtract(positions[i1], positions[i0], scratchDirection); for ( var i = 1; i < numberOfPartitions; ++i) { var delta = i / numberOfPartitions; + var position = Cartesian3.multiplyByScalar(direction, delta); + Cartesian3.add(origin, position, position); indices[i] = positions.length; - positions.push(origin.add(direction.multiplyByScalar(delta))); + positions.push(position); } return indices; } + var scratchX = new Cartesian3(); + var scratchY = new Cartesian3(); + var scratchOffsetX = new Cartesian3(); + var scratchOffsetY = new Cartesian3(); + function addFaceTriangles(leftBottomToTop, bottomLeftToRight, rightBottomToTop, topLeftToRight, numberOfPartitions, positions, indices) { var origin = positions[bottomLeftToRight[0]]; - var x = positions[bottomLeftToRight[bottomLeftToRight.length - 1]].subtract(origin); - var y = positions[topLeftToRight[0]].subtract(origin); + var x = Cartesian3.subtract(positions[bottomLeftToRight[bottomLeftToRight.length - 1]], origin, scratchX); + var y = Cartesian3.subtract(positions[topLeftToRight[0]], origin, scratchY); var bottomIndicesBuffer = []; var topIndicesBuffer = []; @@ -282,14 +318,16 @@ define([ topIndicesBuffer[numberOfPartitions] = rightBottomToTop[j]; var deltaY = j / numberOfPartitions; - var offsetY = y.multiplyByScalar(deltaY); + var offsetY = Cartesian3.multiplyByScalar(y, deltaY, scratchOffsetY); for ( var i = 1; i < numberOfPartitions; ++i) { var deltaX = i / numberOfPartitions; - var offsetX = x.multiplyByScalar(deltaX); + var offsetX = Cartesian3.multiplyByScalar(x, deltaX, scratchOffsetX); + var position = Cartesian3.add(origin, offsetX); + Cartesian3.add(position, offsetY, position); topIndicesBuffer[i] = positions.length; - positions.push(origin.add(offsetX).add(offsetY)); + positions.push(position); } } else { if (j !== 1) { From 4a6cc957043b859642297038fdc76ae9ecae99e2 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 20 May 2013 20:14:55 -0400 Subject: [PATCH 047/306] Add tests. --- Source/Core/EllipsoidGeometry.js | 2 +- Specs/Core/BoxGeometrySpec.js | 2 +- Specs/Core/EllipsoidGeometrySpec.js | 41 ++++++++++++++++++++++------- 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/Source/Core/EllipsoidGeometry.js b/Source/Core/EllipsoidGeometry.js index 443ead6eaf66..ab9d97f3c083 100644 --- a/Source/Core/EllipsoidGeometry.js +++ b/Source/Core/EllipsoidGeometry.js @@ -181,7 +181,7 @@ define([ for (i = j = 0; i < length; ++i, j += 3) { ellipsoid.geodeticSurfaceNormal(positions[i], normal); Cartesian3.cross(Cartesian3.UNIT_Z, normal, tangent); - Cartesian3.cross(normal, tangent, binormal); + Cartesian3.cross(tangent, normal, binormal); normals[j] = normal.x; normals[j + 1] = normal.y; diff --git a/Specs/Core/BoxGeometrySpec.js b/Specs/Core/BoxGeometrySpec.js index 7cab060fd7dd..06d9d8a35d57 100644 --- a/Specs/Core/BoxGeometrySpec.js +++ b/Specs/Core/BoxGeometrySpec.js @@ -12,7 +12,7 @@ defineSuite([ "use strict"; /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/ - it('constructor throws with negative dimanesions', function() { + it('constructor throws with negative dimensions', function() { expect(function() { return new BoxGeometry({ dimensions : new Cartesian3(1, 2, -1) diff --git a/Specs/Core/EllipsoidGeometrySpec.js b/Specs/Core/EllipsoidGeometrySpec.js index 60c57df05b60..0fe48536acb6 100644 --- a/Specs/Core/EllipsoidGeometrySpec.js +++ b/Specs/Core/EllipsoidGeometrySpec.js @@ -3,16 +3,18 @@ defineSuite([ 'Core/EllipsoidGeometry', 'Core/Cartesian3', 'Core/Ellipsoid', - 'Core/Math' + 'Core/Math', + 'Core/VertexFormat' ], function( EllipsoidGeometry, Cartesian3, Ellipsoid, - CesiumMath) { + CesiumMath, + VertexFormat) { "use strict"; /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/ - it('compute0', function() { + it('constructor throws with invalid numberOfPartitions', function() { expect(function() { return new EllipsoidGeometry({ numberOfPartitions : -1 @@ -20,8 +22,9 @@ defineSuite([ }).toThrow(); }); - it('compute1', function() { + it('computes positions', function() { var m = new EllipsoidGeometry({ + vertexFormat : VertexFormat.POSITION_ONLY, ellipsoid : Ellipsoid.UNIT_SPHERE, numberOfPartitions : 1 }); @@ -31,25 +34,45 @@ defineSuite([ expect(m.boundingSphere.radius).toEqual(1); }); - it('compute2', function() { + it('compute all vertex attributes', function() { var m = new EllipsoidGeometry({ + vertexFormat : VertexFormat.ALL, ellipsoid : Ellipsoid.UNIT_SPHERE, numberOfPartitions : 2 }); expect(m.attributes.position.values.length).toEqual(3 * (8 + 6 + 12)); + expect(m.attributes.st.values.length).toEqual(2 * (8 + 6 + 12)); + expect(m.attributes.normal.values.length).toEqual(3 * (8 + 6 + 12)); + expect(m.attributes.tangent.values.length).toEqual(3 * (8 + 6 + 12)); + expect(m.attributes.binormal.values.length).toEqual(3 * (8 + 6 + 12)); expect(m.indexLists[0].values.length).toEqual(2 * 3 * 4 * 6); }); - it('compute3', function() { + it('computes attributes for a unit sphere', function() { var m = new EllipsoidGeometry({ + vertexFormat : VertexFormat.ALL, ellipsoid : Ellipsoid.UNIT_SPHERE, numberOfPartitions : 3 }); - var position = m.attributes.position.values; - for ( var i = 0; i < position.length; i += 3) { - expect(1.0).toEqualEpsilon(new Cartesian3(position[i], position[i + 1], position[i + 2]).magnitude(), CesiumMath.EPSILON10); + var positions = m.attributes.position.values; + var normals = m.attributes.normal.values; + var tangents = m.attributes.tangent.values; + var binormals = m.attributes.binormal.values; + + for ( var i = 0; i < positions.length; i += 3) { + var position = Cartesian3.fromArray(positions, i); + var normal = Cartesian3.fromArray(normals, i); + var tangent = Cartesian3.fromArray(tangents, i); + var binormal = Cartesian3.fromArray(binormals, i); + + expect(position.magnitude()).toEqualEpsilon(1.0, CesiumMath.EPSILON10); + expect(normal).toEqualEpsilon(position.normalize(), CesiumMath.EPSILON10); + expect(Cartesian3.dot(Cartesian3.UNIT_Z, tangent)).not.toBeLessThan(0.0); + expect(binormal).toEqualEpsilon(Cartesian3.cross(tangent, normal), CesiumMath.EPSILON10); } }); + + }); \ No newline at end of file From 9fdbaa7154d4924b686b543b3e8f52682d332d62 Mon Sep 17 00:00:00 2001 From: hpinkos Date: Tue, 21 May 2013 08:44:46 -0400 Subject: [PATCH 048/306] computeNormals uses vertex data in correct way updated tests to reflect this --- Source/Core/GeometryFilters.js | 61 +++++++++++------- Specs/Core/GeometryFiltersSpec.js | 101 ++++++++++++++++++++---------- 2 files changed, 107 insertions(+), 55 deletions(-) diff --git a/Source/Core/GeometryFilters.js b/Source/Core/GeometryFilters.js index ad74dc895e01..d5da941b66f6 100644 --- a/Source/Core/GeometryFilters.js +++ b/Source/Core/GeometryFilters.js @@ -840,6 +840,7 @@ define([ /** * Computes the normals of all vertices in a mesh based on the normals of triangles that include the vertex. + * This assumes a counter-clockwise vertex winding order. * * @param {Geometry} mesh The mesh to filter, which is modified in place. * @param {Object} mesh.attributes.position @@ -852,19 +853,23 @@ define([ * mesh = GeometryFilters.computeNormals(mesh); * */ - var pScratch = new Cartesian3(); - var qScratch = new Cartesian3(); var normal = new Cartesian3(); + var v0 = new Cartesian3(); + var v1 = new Cartesian3(); + var v2 = new Cartesian3(); GeometryFilters.computeNormals = function(mesh) { if (typeof mesh === 'undefined') { throw new DeveloperError('mesh is required.'); } var attributes = mesh.attributes; - if (typeof mesh === 'undefined' || typeof attributes.position === 'undefined' || - typeof attributes.position.values === 'undefined' || typeof mesh.attributes.position.values === 'undefined') { + if (typeof attributes === 'undefined' || typeof attributes.position === 'undefined' || + typeof attributes.position.values === 'undefined') { throw new DeveloperError('mesh.attributes.position.values is required'); } var vertices = mesh.attributes.position.values; + if (mesh.attributes.position.componentsPerAttribute !== 3 || vertices.length % 3 !== 0) { + throw new DeveloperError('mesh.attributes.position.values.length must be a multiple of 3'); + } var indexLists = mesh.indexLists; if (typeof indexLists === 'undefined') { return mesh; @@ -878,11 +883,11 @@ define([ continue; } - var normalsPerVertex = []; - var normalsPerTriangle = []; - var normalIndices = []; - var numVertices = vertices.length; + var numVertices = mesh.attributes.position.values.length/3; var numIndices = indices.length; + var normalsPerVertex = new Array(numVertices); + var normalsPerTriangle = new Array(numIndices/3); + var normalIndices = new Array(numVertices); for (var i = 0; i < numVertices; i++) { normalsPerVertex[i] = { @@ -898,17 +903,23 @@ define([ var i1 = indices[i+1]; var i2 = indices[i+2]; - var v0 = vertices[i0]; - var v1 = vertices[i1]; - var v2 = vertices[i2]; + v0.x = vertices[i0*3]; + v0.y = vertices[i0*3+1]; + v0.z = vertices[i0*3+2]; + v1.x = vertices[i1*3]; + v1.y = vertices[i1*3+1]; + v1.z = vertices[i1*3+2]; + v2.x = vertices[i2*3]; + v2.y = vertices[i2*3+1]; + v2.z = vertices[i2*3+2]; normalsPerVertex[i0].count++; normalsPerVertex[i1].count++; normalsPerVertex[i2].count++; - v1.subtract(v0, pScratch); - v2.subtract(v1, qScratch); - normalsPerTriangle[j] = pScratch.cross(qScratch); + v1.subtract(v0, v1); + v2.subtract(v0, v2); + normalsPerTriangle[j] = v1.cross(v2); j++; } @@ -939,22 +950,28 @@ define([ j++; } + if (typeof mesh.attributes.normal === 'undefined') { + mesh.attributes.normal = new GeometryAttribute({ + componentDatatype: ComponentDatatype.FLOAT, + componentsPerAttribute: 3, + values: new Array(numVertices * 3) + }); + } for (i = 0; i < numVertices; i++) { vertexNormalData = normalsPerVertex[i]; - if (typeof mesh.attributes.normal === 'undefined') { - mesh.attributes.normal = { - values: [] - }; - } - if (vertexNormalData.count > 0) { Cartesian3.ZERO.clone(normal); for (j = 0; j < vertexNormalData.count; j++) { normal.add(normalsPerTriangle[normalIndices[vertexNormalData.indexOffset + j]], normal); } - mesh.attributes.normal.values[i] = normal.normalize(); + normal.normalize(normal); + mesh.attributes.normal.values[3*i] = normal.x; + mesh.attributes.normal.values[3*i+1] = normal.y; + mesh.attributes.normal.values[3*i+2] = normal.z; } else { - mesh.attributes.normal.values[i] = Cartesian3.UNIT_Z.clone(); + mesh.attributes.normal.values[3*i] = 0; + mesh.attributes.normal.values[3*i+1] = 0; + mesh.attributes.normal.values[3*i+2] = 1; } } } diff --git a/Specs/Core/GeometryFiltersSpec.js b/Specs/Core/GeometryFiltersSpec.js index 2c2308ec43a3..504c3bb690ad 100644 --- a/Specs/Core/GeometryFiltersSpec.js +++ b/Specs/Core/GeometryFiltersSpec.js @@ -638,25 +638,40 @@ defineSuite([ }).toThrow(); }); - it('GeometryFilters.computeNormals does not compute normals when mesh.indexLists is undefined', function() { - var mesh = new Geometry({ - attributes: { - position: { - values: [Cartesian3.ZERO, Cartesian3.UNIT_X, Cartesian3.UNIT_Y] + it('GeometryFilters.computeNormals throws when mesh.attributes.position.componentsPerAttribute is not 3', function() { + expect(function() { + GeometryFilters.computeNormals(new Geometry( { + attributes: { + position: { + values: [3, 2, 1, 1, 2, 4], + componentsPerAttribute: 2 + } } - } - }); - - mesh = GeometryFilters.computeNormals(mesh); + })); + }).toThrow(); + }); - expect(typeof mesh.attributes.normal === 'undefined').toEqual(true); + it('GeometryFilters.computeNormals throws when mesh.attributes.position.values is not a multiple of 3', function() { + expect(function() { + GeometryFilters.computeNormals(new Geometry( { + attributes: { + position: { + values: [3, 2, 1, 1, 2, 4, 3], + componentsPerAttribute: 3 + } + } + })); + }).toThrow(); }); it('GeometryFilters.computeNormals does not compute normals when mesh.indexLists is undefined', function() { var mesh = new Geometry({ attributes: { position: { - values: [Cartesian3.ZERO, Cartesian3.UNIT_X, Cartesian3.UNIT_Y] + values: [0, 0, 0, + 1, 0, 0, + 0, 1, 0], + componentsPerAttribute: 3 } } }); @@ -670,7 +685,11 @@ defineSuite([ var mesh = new Geometry({ attributes: { position: { - values: [Cartesian3.ZERO, Cartesian3.UNIT_X, Cartesian3.UNIT_Y] + values: [0, 0, 0, + 1, 0, 0, + 0, 1, 0], + componentsPerAttribute: 3 + } }, indexLists: [{ @@ -689,7 +708,10 @@ defineSuite([ var mesh = new Geometry({ attributes: { position: { - values: [Cartesian3.ZERO, Cartesian3.UNIT_X, Cartesian3.UNIT_Y] + values: [0, 0, 0, + 1, 0, 0, + 0, 1, 0], + componentsPerAttribute: 3 } }, indexLists: [{ @@ -700,17 +722,19 @@ defineSuite([ mesh = GeometryFilters.computeNormals(mesh); - expect(mesh.attributes.normal.values.length).toEqual(3); - expect(mesh.attributes.normal.values[0]).toEqual(Cartesian3.UNIT_Z); - expect(mesh.attributes.normal.values[1]).toEqual(Cartesian3.UNIT_Z); - expect(mesh.attributes.normal.values[2]).toEqual(Cartesian3.UNIT_Z); + expect(mesh.attributes.normal.values.length).toEqual(3*3); + expect(mesh.attributes.normal.values).toEqual([0, 0, 1, 0, 0, 1, 0, 0, 1]); }); it('GeometryFilters.computeNormals computes normal for two triangles', function() { var mesh = new Geometry({ attributes: { position: { - values: [Cartesian3.ZERO, new Cartesian3(1,0,1), new Cartesian3(1,1,1), new Cartesian3(2,0,0)] + values: [0, 0, 0, + 1, 0, 1, + 1, 1, 1, + 2, 0, 0], + componentsPerAttribute: 3 } }, indexLists: [{ @@ -721,19 +745,26 @@ defineSuite([ mesh = GeometryFilters.computeNormals(mesh); - expect(mesh.attributes.normal.values.length).toEqual(4); - expect(mesh.attributes.normal.values[0]).toEqual(new Cartesian3(-1, 0, 1).normalize()); - expect(mesh.attributes.normal.values[1]).toEqual(Cartesian3.UNIT_Z); - expect(mesh.attributes.normal.values[2]).toEqual(Cartesian3.UNIT_Z); - expect(mesh.attributes.normal.values[3]).toEqual(new Cartesian3(1, 0, 1).normalize()); + expect(mesh.attributes.normal.values.length).toEqual(4*3); + var a = new Cartesian3(-1, 0, 1).normalize(); + expect(mesh.attributes.normal.values.slice(0, 3)).toEqual([a.x, a.y, a.z]); + expect(mesh.attributes.normal.values.slice(3, 9)).toEqual([0, 0, 1, 0, 0, 1]); + a = new Cartesian3(1, 0, 1).normalize(); + expect(mesh.attributes.normal.values.slice(9, 12)).toEqual([a.x, a.y, a.z]); }); it('GeometryFilters.computeNormals computes normal for six triangles', function() { var mesh = new Geometry ({ attributes: { position: { - values: [Cartesian3.ZERO, new Cartesian3(1,0,0), new Cartesian3(1,0,1), new Cartesian3(0,0,1), - new Cartesian3(0,1,1), new Cartesian3(0,1,0), new Cartesian3(1,1,0)] + values: [0, 0, 0, + 1, 0, 0, + 1, 0, 1, + 0, 0, 1, + 0, 1, 1, + 0, 1, 0, + 1, 1, 0], + componentsPerAttribute: 3 } }, indexLists: [{ @@ -744,13 +775,17 @@ defineSuite([ mesh = GeometryFilters.computeNormals(mesh); - expect(mesh.attributes.normal.values.length).toEqual(7); - expect(mesh.attributes.normal.values[0]).toEqual(new Cartesian3(-1, -1, -1).normalize()); - expect(mesh.attributes.normal.values[1]).toEqual(new Cartesian3(0, -1, -1).normalize()); - expect(mesh.attributes.normal.values[2]).toEqual(new Cartesian3(0, -1, 0).normalize()); - expect(mesh.attributes.normal.values[3]).toEqual(new Cartesian3(-1, -1, 0).normalize()); - expect(mesh.attributes.normal.values[4]).toEqual(new Cartesian3(-1, 0, 0).normalize()); - expect(mesh.attributes.normal.values[5]).toEqual(new Cartesian3(-1, 0, -1).normalize()); - expect(mesh.attributes.normal.values[6]).toEqual(new Cartesian3(0, 0, -1).normalize()); + expect(mesh.attributes.normal.values.length).toEqual(7*3); + var a = new Cartesian3(-1, -1, -1).normalize(); + expect(mesh.attributes.normal.values.slice(0, 3)).toEqual([a.x, a.y, a.z]); + a = new Cartesian3(0, -1, -1).normalize(); + expect(mesh.attributes.normal.values.slice(3, 6)).toEqual([a.x, a.y, a.z]); + expect(mesh.attributes.normal.values.slice(6, 9)).toEqual([0, -1, 0]); + a = new Cartesian3(-1, -1, 0).normalize(); + expect(mesh.attributes.normal.values.slice(9, 12)).toEqual([a.x, a.y, a.z]); + expect(mesh.attributes.normal.values.slice(12, 15)).toEqual([-1, 0, 0]); + a = new Cartesian3(-1, 0, -1).normalize(); + expect(mesh.attributes.normal.values.slice(15,18)).toEqual([a.x, a.y, a.z]); + expect(mesh.attributes.normal.values.slice(18,21)).toEqual([0, 0, -1]); }); }); \ No newline at end of file From 265e86abd02616d8531208669f0da540e81b9e06 Mon Sep 17 00:00:00 2001 From: Akos Maroy Date: Tue, 21 May 2013 08:53:13 +0200 Subject: [PATCH 049/306] addded initial version of WallGeometry added WallGeometry sandcastle demo code clarifications for WallGeometry --- Apps/Sandcastle/gallery/Wall.html | 190 ++++ Apps/Sandcastle/gallery/Wall.jpg | Bin 0 -> 12043 bytes .../akosmaroy-2013-03-05-LHTL-LHSK-3d.kml | 874 ++++++++++++++++++ Source/Core/WallGeometry.js | 285 ++++++ Specs/Core/WallGeometrySpec.js | 70 ++ 5 files changed, 1419 insertions(+) create mode 100644 Apps/Sandcastle/gallery/Wall.html create mode 100644 Apps/Sandcastle/gallery/Wall.jpg create mode 100644 Apps/Sandcastle/images/akosmaroy-2013-03-05-LHTL-LHSK-3d.kml create mode 100644 Source/Core/WallGeometry.js create mode 100644 Specs/Core/WallGeometrySpec.js diff --git a/Apps/Sandcastle/gallery/Wall.html b/Apps/Sandcastle/gallery/Wall.html new file mode 100644 index 000000000000..f068f7b81c95 --- /dev/null +++ b/Apps/Sandcastle/gallery/Wall.html @@ -0,0 +1,190 @@ + + + + + + + + Cesium Demo + + + + + + + +
    +

    Loading...

    +
    + + + diff --git a/Apps/Sandcastle/gallery/Wall.jpg b/Apps/Sandcastle/gallery/Wall.jpg new file mode 100644 index 0000000000000000000000000000000000000000..df0b0f892e813852f11f133f4119cf54b48bc686 GIT binary patch literal 12043 zcmb7qbyQr*ARG<@0@$y zyX)S6UQO>^wY#c&?Y&l2ch#@wW$9%T0G5$_F9`qwfdD;#E&%ZI48Rq0HaB)PHzWUO z?P^6X^5I1o+{ zKzMB6%K+dt002b%`w9OcAOP;~J0c;&v_vq?KlC3h00;+p4uB9NRyxd|o?0t3MCSPX+-HfB;c&5VkVN)M5V+ zsaV+|=42!5aNE%GJG>f3K)x^lp-cs;3>F0!kcd0GZ^RrpeQe$50w9$EU<1{F2-0HW zELNefahv%KrDA=%Su2nN;Dz&rLxn}r>7l6LSkPup!nT)Q!s&yN6@XJ1K&}!f0}3J! zp$rOfROq-65Y)Tn?-hm@2B-i6pdboRFaq>70j;XXa~}VrpAjHXSQJo(3J#%X3Bjft zmfWxVF2ZrlC$@Qf$=o<0f)gJ>5iA2P7X_CQY#<-jcahCX#O2GpAVLrrekajaY`Up0uS$v_$VmuYpVXw5DO8VT%9GB@cNvWOnbuzuQ z%YAR{`$yK9QeKM{FZ?FEvhfKu*{D2fF4~S-mcI2?37X7AKGT^+0nbJ@nFI>!W|E1_ z5Zgv}@IV2pbt`81Y0q~$7hgq#ly8Isrx+!g%+im+>=$sHaWoA5czoQ|(H?(ynm>{#Nin3nLH+}_D^F-!5zw7k9= zOE;g6daFC%T$8S#`MJUK67R9zjgjuKRJRiFL5g8bBx+Uhv&Kv=dX&< z`kHtH*Ls(WEU$%Nb~i91A@gF5D~84WaD-)3ZGG{-sE4*xcj&I;^CXeMHDfFIyI*Y6&Lld zHd167&-VY#>|fSdX_aNAg}d}TcaLT|k-TqyT53K!57E%jQ2)PEnhZwE$;m0yKmCGf z{&%9)e)j&mCjIYJ{Q?lGTKK@3IbqSL{l5ur8`Cx%nesGA?~7-w|EIwD8hIu3D%WMw z^E>Z8|8V*hsp+_99P8eHMBWl~B9oa3#@UcRQt_9h>_Z-L*xUTHA?La9Jsw!VO@8E% z^OWnvW{uqZX$qosqs#A%+mk#(v$fD+=#4$c<1neOb0Ai=vhHz{$<=lL7kDLu@fh63 zipZtx(h;=>iaaVo=?m|7@gJ=Q1(jxMn|z;@=~0#ylLksh%99nmV#N0j)D#rsoCe!# zc2?x6SH!o7mIhMay}QE6!`b*$sr7}@v-2%goYiQGg!fre^3%oK12GAExOha_NHKm) z86#4&Dntx{F*M!n1u$KCLgAa;JKIR@{B`hXUy6vL%IdASR*O}99JHO+RgD2ZVdTI> zdY&rM)LEN@GKO0`_S2kGulg-e|3dC8m6#jP0e{G<}R3izLA>B-IF(K9XDW>1L z5ZfgB1z=5;Q1xMkr@^K&QgA0_66bAMj1=!hJ96U(CrQ-Zq4x%HHY58-WT?$2*A=#z zt2i5Bk#W*Tp0twQ>(^#8azEpqmXqFKwr#K{o|#a2DgV;3=!Dca5U3$gq4ciFQ31Td?0K~PujLBdJU;xLBO&%<9Ww!Q-MC88<)V~Ob4O^UWpsZkAJP~C?3N~S5rvy=zdh&waX-MGKKg$$6 z5GVw^tW-g0z)>l#NPjc!X@{``v7;n5ZL%%x`?@9w**iF|<(3Nd?BHjZnBFo_e>0__ z5htTn({gsmL+szQ`S$TOMz@H{p_VoRSmggUk~sMv755Q8tMI0s9vz>Dh`-EWOoWR$ z8Bc9hdA)v{CKlfCTlQO&*UZrifCkCP;xwz#ePV@MZjHE&h0@hN=0}IcVOER%II`I) zBeUAVsanr(oP!6fx|*l(rDSHTOaF)uiX*?-n(ut#8moELm3s_4HI=PpKex*3ob-v? zMnXWhv~$TrQ@ipRiK7;_;fp4*65LTX9A%|V^pE9q-CFYps#cZfbFz@?59zg>Y2lxi zTVbz4m65ei#2oT&LjP4CPv*_omcJCldftaJDn{pCth@Q9HuMj~Jx1U14=OBHzvcaa zG0)v@WMZ$%Dfh*W1-Iv+?efgZH;sKya>)xL(C2VO?kpXS$_Jifzfv+AzIuMSGuGc( zUClyCANe;%`)3B-8@XMXq}+2bugJ<%hu-7nj!?*>hb>blHGVbmW@i<7=kkX|<_E&t zwunUXflyeU#*wUvVg@EEu2}JT{qKain8teR=Kj&-5}6SGZM>%>}6Eteh>m-SW-jouJC0+89E50}dI?2QjB0TL1+Qo0eaWF4sz=rLhaER~- zaImEE-(Cub4UYqJQK&L2n+O8AurZ4$g^JVpKkf$}(;h zl{0#3XNJ+`Z;*0|%9_V$az4#lQu>l`RSzoMJh;7E{5f}Kn5Nq4r>}6+_n!8Al$wb9*kh@AL+eQ`nuenvt?tFQolfOs$Ruk<$ouywC)dxZiZ}nmven`YF*4^in!zexiBdM_{t)FA{nMv7tvO#I@ws`g zd8jo>Bdq*$NuH#yAXp+fnHu&6vUAx~iE68>t3e?0pgBenEpcOzDBf@4m}1ZmMx4Z2 zagH-XI4@0RRhh`&&;-S?=nlG0Gr5pIa<{H^I%Q|`tl3r%jxo;ZO((# z4UfV~wjV!5?N0bpv}@LooplK`C}0PBtD?|ukcEM0fADZOv&NZ4wNK@l8S~icq?aX% z5O5b_7S6rLNuyRTk@$3XEmA#hB2ZXt6r<|o{>sEL&IC2Y(G7y86zocibelgKse;)l zt6cshQhI^F!!|uMzWV$=EfQp%n@w3ONdeRa7*rE$>j;)+3}u z@q&4~FX^&Ix^ncE3@Pat_}-W+$hBU+rH{R&enp#L-MOZwV^e0mHd^|TMywqt=z$Gy zP0 zOfF{Hck%CJ4oL{^QmKpAcUir<%nQG_^`q=}hjoV?%w>hn;VslKYscndm+Idgs5KF8H5J{Q+zHf0m_A95rju zW=#DrA&Jv?!`x&!XN>ma+vC;FG0x1XKe(DPvnPYb243Y~uC)aAAI&}gj1{TfV$J)^ z+iyKq(W%ka8y9?Oe*U>ld-gjm;subj`c)dUwHD&AVLgNn{JctIEc*jf00WW2NodpX9b(!oGxzy|Yd3oBeP@)^+k@0CR3T34 zi6c$nXWatVmNs+^ob`F?mAl^y1kUZQah|&8yNv=WpZoac#LP)aWRXaJM(9%re(yAS z0gSrZ>k|up>#1VZCwxi-$NS2BTIEt@H=Sa2>Be@a=fF+*3t+C4V>W%m<}F?($q=|HwZ&LM)xiY8;1)Y8nnA0N%1&6my?2`} zLSQ7&<#Z<#+1`UF;}%b{5_>h6owo-Kj(}~zqC2V;kvoX3XSbl}^z9e@h1NDlB-JPz zopq?OdWbLe6y}lhRIC9?*&6vC(JDX-?V+uZ3^R|L+A4Si5i4>Rl4M%y%;=)`izx+e z_48gt$Pxm{?wOR$Y$|UVyt{QkXJ5_DRqQF9&QX9lzj8xSu5SDALYL?5c`{j)mSfIH z7>;hg^MZEZZUj*&Zrf%x5B{%-_i+uO+q~5oZD(TY(A9dS+thX|zsSly!?}WLX8NOA z3`*ygz_4aCQ!OW^vMII9u!q&i&wa=lV16e7!p-G}~q3G#%qIPTO(mLAX6` zHOKKv1L}56`YlFx749Mr_C8}m8pE7HmCwtc8%YLsTWnrQWfA0?FS;NjNaQ=CBe=g= zhdiWG!WQKoYnbNz+-p#4v>s)!4M6pe=dUvHORm`*uP;_3u zBPrl1QYmp>+!ivTkK%!$VQ{SD>b}EtYkR1X$6r%k#RS?+@cify=?}X`s$eGINa*EI?@sx05ptZR zvg}CaZsI(l;f?qXzW;r>632HNBfnTWg5F84M6-(twKfSZv?v?353&gRW+M}X(MU#n zHBNnY^2WoNnJuX~IY|i`X|mi51c+^$yYwALaxI38+5YA_60E&FCyxn;<82NEz||~* zppse)hJ7M$qnd2&ps7w=b+{8Bl0T&o>k3__q@%lnE!H+k_&d6mL#l0-KWFMIy=jUn zO|mGsji`HBQK6ypnTxx?k#EJz&G7R4T5GZx?Xf7o$~7)e_mVt+_OmB0SDBJ=II#Is z-F`~rh_~~mQiLev*pat4UD&F^;ith>+oXs&I7RPyIFDjiQM#Y4-vo~_+eW(zE`LVd1`v0@RQOQdksV;Sj|Sv7FP~K@`$8C^t@2yp*232+YTYSYqdBZ-ILCRp zy*BHkn^`^XmygVI^!P0fSzKYPnNx9p&KdL=83!g5)b~z<&&h=^{*}hV&;}vs)8MOXVE~XIjFg7Nl!zgeIwiy& z2**JsF3bR`-vkiQY+I%-u>hiD1gxT1iwiLjpbn%-H}Cwb-~fOy*|dcJ z)@4&uIFlNaM&$U?GDpr|M`;KWO#PM&4-5aNh5e=Q@bH~6F+n9d=g@J#Ena_+|KNSH z{{fBO*SH2Vle3)z_*Ib1sJl-_G7k>i<`qa|l}ga))^W{X5SbnQR2uENvoN&rrgc+; zhj$4t7~X4HCyDPpv@u=`om-=KD0ssip?3NrLuH*HfeDE-9>o4s#1LsZ$uS6y z=64d|F`YK8gacDl<4uWZf$&v6VS9@#G9o%Guivpir}Cs5KpTI`A)GR2+e5&rMln`o z8td5V!3!oRrqLNnZx^ z9w&g_xwW_lmJJ0Kzw0x%Kd(n~sug(wprgwiGWSHnPidb5n8nGHHMoVzz>(%$((zIs zoW?Ly&H!*M5QIF4<*JDIr`i5Qr)4~-Q=I_CPvK&b^BgOB%L{^;|a?{1TWygN2pzyko z(Y#q0$})E&)MWy`?OEN5nj#q+ua%yA%zHF)C5^ZXi$np?cdyfm47N5^NTVfO(XcNT z2uL5ZGz5TY%S?~(q9JyAMRy2aaS-gb^MjLFC$QQNsvOtZu*OtcKrA%gLQ1$JIBWv5 zE?<41()rh%?io-jKpKW-NxpZ*z@0G9BBN2sPEZ*gdO$&2~qY7?Ksk0^as@b{9a5JJH46%dK{aws+)07{jQ*@%-J_)LTI-30W!e2Y}tg>b1 z8>MqH1!1*qaDG%|k`tX#aXI?yE)j>>H7E z;$z2RUUFp`<4Rx;kjOD0q6$2-6lO$U6}0hGrkYYzC)rhq0uT@|YT+Ob;C>7SOW2~_ zhJvST125L`z6kda08awqWLEWc0CWO>P~3`r*x0-T!w`@r0%XBUr>@~X1NddUq;;x| z7s6UH!8zKO*BOjGs6P(un=wC;SI&_raN~I&kmqu>cLIGG(XYNuzRLAx%O% zfg`Hc^wV~nk0$Z(qJV15fHef|Up#MIxeq?gfOqORi!kCO4(2@RjNvJgCGNOmMp27} zU0GJi&m&J72C zp4wQmhAd@Ck^suVE`GTv1{wle#yjf8h?$cNw)jxhDq2*`pgx^JE4Gb6i56j(+^$w2 zz!p}b@+>U^l!~WLq7`A)+&`yTfWHtKShbz|DbbFmX=ZN6U6{-6xmB2U!n^+@vVmJZ z(vN+oHNU&5#V|4Kj5gI`1l;llv8lINptHqzeRkH!vsRdE3Lrv`(h_L0VUaYj;*rBy z((f}u-tT>jyHwyFd1Ru}L34_?5aPhF--(?ds&vlwHYg!3^ez_~*8ZnoXngd}1c6+I zF+!=hqU-z906fAyRQSpS#!PiI$7;?4in!p5GQrgbEDC3h_w!bYyFFuy+ufr1omp(qDy zs5bpY=hn50WF`)e1`4V_G5k+G@tQTre)ROIn zYAWpS>I$5Vq|`|!8#?a3?iOwPP1n84IX7@hkdc?*HI242__PEKT_AH(C8Hx&os?NCp12bE2`)*x$pwQD>vy2_Y0o0T%@g95DtMi z-+m0Yt=}+@Iz=Z&^x!emWMn>mn%>v~r8*X#S1ij8J!fk1O5X||afcgi|ndzV#y)3&Z})yOu%ias)y^7D@LXGMnJ#)sj7wrmKc zNb$E_rZFiftcLr@<4HNxdPAvm*w})Sl@eu3%W-gu@JL$cR?+$*;NEkt(fG+rNH0LYjA;SDc<@P_ZOLo+nkvH0H$^&#!*ne_J)$-&1b zkjCXT#L7>)tFkU@Y(#f#g!Tv|87v#>9X(Pq-RjTig|S|;Sp#P)0%wvNEq7x|c%*-z zWwT^gj$1G;_7ep%?d2Hfk|!`c_CQ>CM}K%^1Am3@?1B*K(Wv$`M0M~d$)ai*G6O#LgTBvNa>M4D)47gj@Zpb zgNtLV5!)sX?uwHWD((_)Wa(xzBh!XSRJnLAe-3XUx*fEPmTeoV zFzSU-w#K^nT5a|23rWblDREicFB`;AQ~po3pTNs+Dl{&$A!Y~0JsMed$f|I^&d$ z+aK2nElm#|aV88Vil}dUh3fhc+D(~=#YE-pCBK<9v1m#h@L12zt%k~C;k)$iQyu50 za|QR;nbQPk?wiQ8oL`gKpeqYvIl+MmW1n4`VrDG zod)8v#TC%uGK}fkS#Xs^UZb-j1;3w}K|?-7a-&La-c59n-$FHb0U)sSql1enQ4pfp zH#T!&&v*AYclWg2y#mk3c^G&81?25y|5U)Rz=4Ai@V|Dqe=1;Q5n~u`3xjOW!M)QL zpNALITib<}Kgt z_DDltyN{Yn)6F=}ey+MS4vqaemg-}A968MNYC&k%N9Z28^xja*Y&?YV43)s`RWTxh zU6<{inPxNGz)4{oE=hoAO?K-Xd;nlNU_B(BLN)ITbOEGq+3xsg8b15F{eCCq1rXzw zvf$&g6JA5M!)8F*W_H~_i%!7u*zed??`!fnyhx_!%f1u)WO|tQ`hI^H_D=+K0d|-* zY5PV0B9bT+zw#IFx@c` zEB|>ZK+{n|q2FN^mB6||s+xa!$?E45^9tFpGogwEmIqJd=BrzFFXRfcE*$9B#yq}u z`&Vm!>PHt9{)E3;zW$7{)wzk%;8QJ2T0BwQC8s#}gsDeq<9e-{7d@qE(Kjg{9qPjn zT%jj|^TAc~$D=|6fznB?&(zKWmGYY=@2L-GRgy}OVttP||4Ddn-6dbl`uI$%Y!wWN@Iz2JYGtmcVJ z*CD;Xi_Vv4BpcZjL(XBpWi6sRoE0>s)C{u|ESHN#hI2}2V)|m6JNfzXVNhgDTHp{% zfQLy`nJ@>ko?jEbt&W}QvT>01x9jWmP_?tk8QKz zbOwFp+ZbZ!axvtAblu$r1lASomSYGKD-us?eL}&KvM$v#kvsTWeaZKDGeoLxjN*W% zI4XFFv>u>*6#e8B_Q5Mu&=pJ2?wFx%Cct88?k4zsfl}~x#l`GZgs^1?L~6P#+X<7% zKM3nCD4X$pSvpcp%ChGNLv~uhJiTzF2eepQ)S5~(gsb8gfK$FGqrOAJg(IAqU~Q^- zLA<+ZNAmAnmR@nlT}#Zt-K3T|#=WEAYs0TRUl6QosR!;Tex~gTB-IjHm0@Xxu2>Y` z43WEMN8+o0PW`!~w~yAW4yNOX$?|aus>dW>$P@TJOe(Jv@G}r-;_l2$_|E7u92-f< zIGG{-2w;VNABGzz@`*na8P~wahzl?$@+GNv#ou;1{F626^z2nwa-!5xh@wUP7EiOmHUL|mi^84h)Vvm74m_d=`gNMjAMfk)W7w1Ww@Zo(J4HfRJz{c`G--3ZhxJf^f z)Q~~v9i(Z$j=5gH+7M;9^J_5S%ecOH+6$~+M^lgd*n7?{O>m45z-h=qg9Xmj1vN3F za5>PGDgdt&JqY!4t+uRpGrw~01K*$)^S6fUxx|~aR^bfpMq}|ChrSYikBXt1G=#Dg zP<>J6FvoH&B0j)p>l2sDuIiV{g}9=KH({=W|M(j3+JORq!sRWy9UO6Cf*yk#WkSqN znMz6vKJTW8(y$AA zp}+=*T)hsfo@ColA_cT#5M>1Or-$;Z-(v?Jg!#C_Hi0c`Vxlq#O1ijFwNIwcaEXPe z0!=5p94o$b@$h4Bx$vr-096z{=Y4ZbO#&k^a{12cBD{DuACYMzT;${RGhgAnD<_A0 zD`s=$zD~mfma*d?#e@Ecl{r^<OU>jK7NGpDmERNyAKDRgaV;Ahb$yR? z$jiI?M;Id}T(-RxR~MZ_)$*fr&m~4JJbcrHAz`6Z?Aas-lmsPbP4mkY>yb3~aM1#G#Rkq|*6$b3C9R-CS!h5o8t?6QX2Hb+| z_J%uK%s9%Upb0!vp&g;RfsV-lX7usvycrw zU?EsXty3+%)8Zg3HstiM4*Xz6C6Hw>9;8P<<;EfW0tg);Ii7Mblh*SXHTqH(p#Bx< z*H)N0PGE_C$d-+gQvQ$zPrtT{-iY`kc5ajiUWxtc8h|;d(UT+ + + 03/05/13 LHTL-LHSK - 3D View + + + 03/05/13 LHTL-LHSK - 3D View + #flightpath + + 1 + 1 + absolute + +18.9928799,47.3374825,108.8888 +18.9928799,47.3374825,108.94976 +18.9928837,47.3374825,109.1936 +18.9928799,47.3374825,109.22408 +18.9928799,47.3374825,109.0412 +18.9928799,47.3374825,109.0412 +18.9928799,47.3374825,109.346 +18.9928837,47.3374825,109.22408 +18.9928799,47.3374825,108.94976 +18.9928856,47.3374825,108.91928 +18.9928837,47.3374825,108.85832 +18.9928837,47.3374825,108.85832 +18.9928837,47.3374825,108.8888 +18.9928837,47.3374786,108.8888 +18.9928837,47.3374786,108.91928 +18.9928837,47.3374786,108.82784 +18.9928856,47.3374825,108.82784 +18.9928837,47.3374786,108.67544 +18.9928856,47.3374786,108.70592 +18.9928856,47.3374786,108.52304 +18.9928856,47.3374786,108.52304 +18.9928856,47.3374786,108.49256 +18.9928856,47.3374786,108.61448 +18.9928856,47.3374786,108.4316 +18.9928856,47.3374825,108.52304 +18.9928856,47.3374786,108.52304 +18.9928856,47.3374786,108.40112 +18.9928856,47.3374786,108.52304 +18.9928856,47.3374825,108.4316 +18.9928856,47.3374825,108.49256 +18.9928856,47.3374825,108.64496 +18.9928284,47.3374901,108.584 +18.9926281,47.3374939,108.8888 +18.9923820,47.3374252,108.7364 +18.9921074,47.3372917,109.346 +18.9917793,47.3371201,109.346 +18.9914131,47.3369370,109.52888 +18.9910259,47.3368263,109.74224 +18.9906693,47.3368568,109.71176 +18.9906139,47.3368988,109.98608 +18.9906120,47.3368988,110.01656 +18.9904995,47.3369865,110.01656 +18.9891090,47.3381653,110.13848 +18.9878616,47.3392105,110.4128 +18.9864006,47.3405342,111.29672 +18.9846992,47.3419991,121.17224 +18.9829159,47.3435364,136.07696 +18.9811440,47.3451004,161.7716 +18.9797153,47.3463669,182.77232 +18.9776611,47.3481560,205.358 +18.9738159,47.3513412,222.79256 +18.9717865,47.3530617,241.05008 +18.9697704,47.3547096,269.27456 +18.9676800,47.3562927,290.8544 +18.9659195,47.3576126,304.50944 +18.9633121,47.3594894,320.63336 +18.9609356,47.3610916,333.73976 +18.9584579,47.3625793,351.60104 +18.9556198,47.3635788,374.64392 +18.9525986,47.3640480,395.33984 +18.9495506,47.3640366,411.12848 +18.9464779,47.3637772,420.66872 +18.9433651,47.3633690,430.17848 +18.9408531,47.3629303,440.26736 +18.9371738,47.3622627,461.81672 +18.9346943,47.3617668,472.78952 +18.9316044,47.3610649,486.0788 +18.9280968,47.3601494,501.34928 +18.9252472,47.3592453,515.40056 +18.9202175,47.3575249,540.05888 +18.9140663,47.3554077,571.63616 +18.9112453,47.3544388,587.18096 +18.9084339,47.3534813,603.00008 +18.9056110,47.3525200,615.28352 +18.8995743,47.3504524,614.91776 +18.8963146,47.3493080,610.49816 +18.8929195,47.3480759,608.42552 +18.8895607,47.3468361,606.38336 +18.8861523,47.3455505,605.34704 +18.8827686,47.3442497,605.7128 +18.8793640,47.3429413,606.04808 +18.8759556,47.3416100,605.77376 +18.8725376,47.3402824,605.28608 +18.8690987,47.3389397,605.34704 +18.8656864,47.3375969,604.70696 +18.8623295,47.3362732,606.23096 +18.8589458,47.3349495,606.35288 +18.8555679,47.3336182,606.23096 +18.8522282,47.3322906,606.26144 +18.8488216,47.3309326,606.17 +18.8454056,47.3295631,604.55456 +18.8419857,47.3281784,604.37168 +18.8386021,47.3267212,603.2744 +18.8356552,47.3249588,605.8652 +18.8330593,47.3230324,606.07856 +18.8304825,47.3210754,604.31072 +18.8278923,47.3191147,603.18296 +18.8253078,47.3171539,602.93912 +18.8226776,47.3152351,603.39632 +18.8199825,47.3133507,603.76208 +18.8172626,47.3114738,604.06688 +18.8145275,47.3096046,604.21928 +18.8117924,47.3077393,604.21928 +18.8090534,47.3058662,603.85352 +18.8063164,47.3039970,603.39632 +18.8035793,47.3021240,603.09152 +18.8008480,47.3002586,604.06688 +18.7981110,47.2983971,604.06688 +18.7953720,47.2965317,603.94496 +18.7926216,47.2946587,603.18296 +18.7898788,47.2927933,603.09152 +18.7870464,47.2909813,603.5792 +18.7845478,47.2896309,602.17712 +18.7807808,47.2877007,603.15248 +18.7782516,47.2863960,603.76208 +18.7744789,47.2844467,603.70112 +18.7713375,47.2828293,603.51824 +18.7681904,47.2812080,603.39632 +18.7650433,47.2795906,603.15248 +18.7619114,47.2779808,600.62264 +18.7586422,47.2763786,589.49744 +18.7550888,47.2748566,575.26328 +18.7514668,47.2733269,562.33976 +18.7478065,47.2717667,548.80664 +18.7405167,47.2686234,523.44728 +18.7368889,47.2670593,511.77344 +18.7332687,47.2654953,501.19688 +18.7296505,47.2639313,488.33432 +18.7260056,47.2623901,476.75192 +18.7223225,47.2608871,463.3712 +18.7186356,47.2594070,452.76416 +18.7149429,47.2579498,441.7304 +18.7112598,47.2565117,429.5384 +18.7075939,47.2550583,417.71216 +18.7039585,47.2535973,406.43456 +18.7003155,47.2521362,395.30936 +18.6966553,47.2506752,382.38584 +18.6929703,47.2492294,370.1024 +18.6892929,47.2477760,358.00184 +18.6856384,47.2463036,346.66328 +18.6820107,47.2448006,335.08088 +18.6783943,47.2432709,322.82792 +18.6754627,47.2420082,312.4952 +18.6718769,47.2404366,303.8084 +18.6683693,47.2388611,304.44848 +18.6642971,47.2370186,303.56456 +18.6615429,47.2357750,304.7228 +18.6581402,47.2342949,305.942 +18.6547642,47.2328110,305.97248 +18.6481171,47.2298279,308.5328 +18.6447735,47.2283707,306.18584 +18.6414452,47.2269211,309.752 +18.6340828,47.2238197,306.61256 +18.6313229,47.2227058,309.9044 +18.6279144,47.2213058,306.3992 +18.6238689,47.2196045,306.3992 +18.6210804,47.2184525,306.52112 +18.6175976,47.2170601,307.37456 +18.6141205,47.2156334,304.69232 +18.6071377,47.2128105,306.67352 +18.6037064,47.2114143,305.42384 +18.6003170,47.2100410,308.59376 +18.5969334,47.2086716,306.18584 +18.5935459,47.2072868,307.34408 +18.5901966,47.2058754,308.41088 +18.5868340,47.2044792,306.27728 +18.5794601,47.2014275,303.99128 +18.5767593,47.2003098,306.36872 +18.5734310,47.1989555,307.58792 +18.5633640,47.1949120,307.70984 +18.5600071,47.1935120,307.74032 +18.5566063,47.1920891,303.93032 +18.5532188,47.1906815,305.60672 +18.5498276,47.1892776,305.82008 +18.5464401,47.1878929,306.73448 +18.5430241,47.1865349,305.942 +18.5396099,47.1852074,304.53992 +18.5362377,47.1838799,307.466 +18.5329094,47.1825523,307.7708 +18.5263309,47.1798210,310.48352 +18.5230179,47.1784286,306.76496 +18.5196629,47.1770821,306.67352 +18.5162983,47.1757050,307.34408 +18.5129471,47.1743126,306.704 +18.5062294,47.1715698,304.17416 +18.5028534,47.1702232,305.05808 +18.4994678,47.1688995,306.42968 +18.4961052,47.1675606,309.05096 +18.4927368,47.1662064,307.6184 +18.4859467,47.1635094,305.54576 +18.4825478,47.1621475,305.0276 +18.4791756,47.1607475,303.38168 +18.4758167,47.1593590,304.1132 +18.4725246,47.1579742,306.03344 +18.4691944,47.1565666,304.08272 +18.4658184,47.1551895,307.466 +18.4624805,47.1538162,306.73448 +18.4591274,47.1524429,303.74744 +18.4557724,47.1511040,307.25264 +18.4524117,47.1497726,305.75912 +18.4457359,47.1470871,315.51272 +18.4424973,47.1458282,331.2404 +18.4393368,47.1446114,346.54136 +18.4332714,47.1423416,383.72696 +18.4302864,47.1412125,406.43456 +18.4274025,47.1401138,426.24656 +18.4245644,47.1390381,435.6344 +18.4217186,47.1379585,439.71872 +18.4187775,47.1368866,445.93664 +18.4157352,47.1358299,460.0184 +18.4127541,47.1348305,478.94648 +18.4097443,47.1338196,495.5276 +18.4067993,47.1328506,514.21184 +18.4038849,47.1319084,529.48232 +18.3980122,47.1300087,549.1724 +18.3949947,47.1290436,567.94808 +18.3921528,47.1280174,578.67704 +18.3862743,47.1259880,605.98712 +18.3832588,47.1250153,611.0468 +18.3801060,47.1240120,611.74784 +18.3734112,47.1218605,603.51824 +18.3699913,47.1207542,602.90864 +18.3665295,47.1196327,599.70824 +18.3630524,47.1185036,600.2264 +18.3595428,47.1173515,600.40928 +18.3560390,47.1161842,599.95208 +18.3525162,47.1150284,600.2264 +18.3490124,47.1138611,599.89112 +18.3454800,47.1126633,599.55584 +18.3419971,47.1114388,597.45272 +18.3385181,47.1102142,597.9404 +18.3350544,47.1089897,600.5312 +18.3315239,47.1077690,599.49488 +18.3279514,47.1065292,598.21472 +18.3244171,47.1052513,599.09864 +18.3209190,47.1039696,597.90992 +18.3173542,47.1026993,598.36712 +18.3138180,47.1014328,598.03184 +18.3102970,47.1001816,598.82432 +18.3067417,47.0989532,598.73288 +18.3031559,47.0977325,598.33664 +18.2995758,47.0965233,598.33664 +18.2959709,47.0953140,598.94624 +18.2924118,47.0941048,597.90992 +18.2888279,47.0928917,597.30032 +18.2853050,47.0916748,598.03184 +18.2818317,47.0904427,599.58632 +18.2783813,47.0892143,601.26272 +18.2749100,47.0880165,600.34832 +18.2713985,47.0867844,598.00136 +18.2678852,47.0855179,595.89824 +18.2643967,47.0842705,595.502 +18.2608814,47.0830193,596.1116 +18.2574387,47.0817833,600.74456 +18.2539616,47.0804787,595.502 +18.2505074,47.0792122,597.39176 +18.2470150,47.0779877,596.02016 +18.2436199,47.0767212,598.79384 +18.2402954,47.0753937,600.074 +18.2370586,47.0740395,600.3788 +18.2338829,47.0726089,601.41512 +18.2307796,47.0711174,598.97672 +18.2277050,47.0695915,599.0072 +18.2246761,47.0680962,603.36584 +18.2216034,47.0665894,599.49488 +18.2184601,47.0650597,588.9488 +18.2152348,47.0634651,574.53176 +18.2120609,47.0618095,561.73016 +18.2087879,47.0601120,550.63544 +18.2055397,47.0582962,542.68016 +18.2022610,47.0564575,525.94664 +18.1988983,47.0546608,513.44984 +18.1954823,47.0528679,503.4524 +18.1920986,47.0510330,489.7364 +18.1887569,47.0491791,478.64168 +18.1854687,47.0473595,469.22336 +18.1821423,47.0455170,454.86728 +18.1788597,47.0437393,442.7972 +18.1755333,47.0419807,431.48912 +18.1722946,47.0402679,420.91256 +18.1690903,47.0385246,409.90928 +18.1659622,47.0368118,399.2108 +18.1628838,47.0350037,389.3048 +18.1598072,47.0332298,377.63096 +18.1567059,47.0314445,365.86568 +18.1535835,47.0296822,356.11208 +18.1504669,47.0279617,343.28 +18.1473732,47.0262718,332.36816 +18.1443005,47.0245171,321.82208 +18.1411533,47.0228996,328.61912 +18.1375237,47.0217819,333.09968 +18.1292839,47.0216942,331.60616 +18.1251545,47.0223351,328.9544 +18.1210003,47.0230980,322.4012 +18.1168575,47.0239334,320.1152 +18.1126709,47.0248184,318.7436 +18.1086407,47.0256996,320.20664 +18.1045952,47.0264587,321.54776 +18.1004810,47.0270767,317.61584 +18.0963516,47.0276642,317.6768 +18.0923672,47.0282478,326.57696 +18.0883427,47.0287628,329.564 +18.0843945,47.0292549,330.87464 +18.0803928,47.0297318,331.63664 +18.0763931,47.0299911,333.19112 +18.0724087,47.0301361,336.66584 +18.0684280,47.0302658,336.33056 +18.0644302,47.0302582,332.1548 +18.0604210,47.0301437,329.59448 +18.0563335,47.0300255,325.87592 +18.0523129,47.0297813,320.96864 +18.0483093,47.0293579,319.84088 +18.0444260,47.0287323,319.26176 +18.0406322,47.0278893,315.02504 +18.0369530,47.0269203,305.88104 +18.0332355,47.0258408,297.01136 +18.0297642,47.0245018,300.18128 +18.0268364,47.0228271,300.72992 +18.0244980,47.0208435,298.84016 +18.0226364,47.0186920,303.74744 +18.0208149,47.0165710,312.83048 +18.0190907,47.0145302,320.08472 +18.0173397,47.0124969,322.88888 +18.0155811,47.0104523,327.24752 +18.0138531,47.0084724,333.28256 +18.0119896,47.0064850,333.55688 +18.0100441,47.0045166,332.73392 +18.0080261,47.0025215,332.3072 +18.0060291,47.0005455,334.47128 +18.0039730,46.9986076,334.01408 +18.0019226,46.9966087,331.088 +17.9999771,46.9946175,329.19824 +17.9979668,46.9925919,324.77864 +17.9957504,46.9906120,320.1152 +17.9934082,46.9886627,315.14696 +17.9910450,46.9866943,311.76368 +17.9885921,46.9847641,313.4096 +17.9858665,46.9829979,314.41544 +17.9827785,46.9814911,314.84216 +17.9795322,46.9801216,318.62168 +17.9758358,46.9794197,322.8584 +17.9720993,46.9787178,316.3052 +17.9688549,46.9773521,309.56912 +17.9660358,46.9756355,309.17288 +17.9632740,46.9739151,314.56784 +17.9606037,46.9721794,315.90896 +17.9579468,46.9704361,315.87848 +17.9552689,46.9687042,315.32984 +17.9525623,46.9670334,319.99328 +17.9498863,46.9654007,324.77864 +17.9446449,46.9619713,320.90768 +17.9421349,46.9601860,325.87592 +17.9397678,46.9583778,326.0588 +17.9374866,46.9564667,323.80328 +17.9355640,46.9544258,334.98944 +17.9338417,46.9524117,356.17304 +17.9321899,46.9504280,373.88192 +17.9305897,46.9484634,387.35408 +17.9290543,46.9464836,396.9248 +17.9275932,46.9444313,402.19784 +17.9262390,46.9423294,416.00528 +17.9249172,46.9402733,435.11624 +17.9236298,46.9382515,454.13576 +17.9223843,46.9362755,468.8576 +17.9211254,46.9342880,478.27592 +17.9198532,46.9323540,502.72088 +17.9186001,46.9305000,522.9596 +17.9172688,46.9285889,521.16128 +17.9157772,46.9266357,523.53872 +17.9141750,46.9247322,527.62304 +17.9124050,46.9228745,529.208 +17.9107018,46.9210472,531.98168 +17.9090900,46.9192238,544.47848 +17.9077091,46.9174690,564.77816 +17.9064121,46.9157448,581.11544 +17.9027920,46.9127731,601.65896 +17.9005241,46.9114799,599.03768 +17.8979568,46.9101562,596.53832 +17.8949299,46.9090996,604.15832 +17.8913155,46.9091148,607.8464 +17.8879299,46.9104347,599.37296 +17.8855190,46.9127808,582.33464 +17.8826771,46.9148026,596.38592 +17.8790398,46.9152374,617.32568 +17.8757439,46.9144325,604.61552 +17.8724957,46.9132080,573.43448 +17.8691769,46.9118805,554.07968 +17.8657131,46.9105644,543.65552 +17.8622360,46.9092941,528.5984 +17.8587513,46.9079971,506.89664 +17.8552570,46.9066544,487.66376 +17.8517475,46.9052353,469.74152 +17.8482342,46.9038162,454.89776 +17.8447323,46.9024048,442.37048 +17.8412304,46.9010277,427.00856 +17.8377075,46.8997002,411.52472 +17.8341675,46.8984261,397.59536 +17.8306141,46.8972092,384.18416 +17.8270493,46.8959885,365.28656 +17.8234768,46.8947411,351.3572 +17.8199100,46.8934746,337.42784 +17.8162918,46.8922119,322.61456 +17.8126717,46.8909264,307.25264 +17.8090839,46.8896446,299.29736 +17.8055725,46.8884277,297.43808 +17.8021145,46.8872261,301.9796 +17.7986813,46.8860207,302.95496 +17.7953148,46.8847847,301.73576 +17.7919712,46.8835335,303.68648 +17.7886600,46.8822670,305.14952 +17.7853451,46.8810081,304.17416 +17.7820187,46.8797264,301.55288 +17.7786674,46.8784637,300.97376 +17.7753086,46.8772163,302.77208 +17.7719364,46.8759842,302.07104 +17.7685776,46.8747673,301.64432 +17.7652626,46.8735352,304.23512 +17.7619629,46.8722954,303.86936 +17.7586594,46.8710594,305.97248 +17.7553520,46.8698349,302.77208 +17.7520084,46.8686447,304.66184 +17.7486496,46.8674660,305.54576 +17.7452850,46.8662796,304.5704 +17.7419167,46.8650856,303.41216 +17.7385559,46.8638992,304.38752 +17.7351971,46.8627205,304.99712 +17.7318535,46.8615417,304.29608 +17.7285252,46.8603630,305.36288 +17.7252140,46.8591728,306.06392 +17.7218914,46.8579674,305.27144 +17.7185650,46.8567390,304.69232 +17.7152214,46.8554764,305.3324 +17.7118549,46.8542252,302.4368 +17.7084656,46.8529587,300.82136 +17.7050819,46.8516769,300.7604 +17.7017174,46.8503838,300.9128 +17.6983757,46.8491096,301.0652 +17.6949844,46.8478546,300.21176 +17.6915569,46.8466301,300.05936 +17.6881180,46.8454170,302.10152 +17.6846981,46.8441887,301.12616 +17.6813354,46.8429337,302.77208 +17.6779633,46.8417015,302.68064 +17.6745739,46.8404808,302.25392 +17.6711788,46.8392601,301.2176 +17.6677914,46.8380356,302.01008 +17.6644020,46.8368187,301.94912 +17.6610031,46.8356094,301.27856 +17.6576004,46.8344307,299.9984 +17.6542168,46.8332710,299.72408 +17.6508732,46.8321419,302.07104 +17.6475773,46.8310165,305.85056 +17.6442871,46.8298950,307.43552 +17.6409435,46.8287621,305.97248 +17.6375370,46.8276138,302.4368 +17.6340733,46.8264160,297.62096 +17.6305618,46.8252144,295.85312 +17.6270828,46.8240204,294.99968 +17.6236687,46.8228378,300.33368 +17.6202602,46.8216591,300.82136 +17.6168442,46.8204651,297.34664 +17.6134510,46.8192825,298.90112 +17.6100864,46.8181229,299.14496 +17.6067505,46.8169975,304.20464 +17.6034317,46.8158798,306.18584 +17.6000996,46.8147316,301.18712 +17.5967770,46.8135605,300.36416 +17.5934505,46.8123970,300.48608 +17.5901184,46.8112450,299.57168 +17.5867786,46.8100967,299.66312 +17.5834732,46.8089752,300.05936 +17.5802002,46.8078537,302.98544 +17.5769329,46.8067474,304.53992 +17.5736465,46.8056450,304.02176 +17.5703678,46.8045197,303.71696 +17.5671024,46.8033905,306.03344 +17.5638027,46.8022537,303.71696 +17.5604706,46.8010902,302.52824 +17.5571232,46.7999268,299.72408 +17.5537071,46.7989388,310.48352 +17.5501041,46.7986488,326.3636 +17.5465145,46.7991333,330.90512 +17.5396042,46.8012543,342.03032 +17.5363598,46.8025894,353.21648 +17.5334587,46.8042412,362.87864 +17.5311108,46.8063049,363.18344 +17.5291729,46.8085861,359.95256 +17.5272598,46.8109818,359.46488 +17.5254135,46.8134460,360.86696 +17.5235443,46.8159218,361.50704 +17.5217781,46.8184471,364.06736 +17.5200291,46.8209953,364.37216 +17.5182648,46.8235588,362.75672 +17.5164852,46.8261566,365.77424 +17.5147190,46.8287468,368.15168 +17.5130081,46.8313980,364.616 +17.5113869,46.8341026,362.6348 +17.5104389,46.8369179,366.26192 +17.5103130,46.8397560,370.01096 +17.5106525,46.8425941,372.81512 +17.5112133,46.8453331,370.46816 +17.5119877,46.8480721,368.09072 +17.5128059,46.8507957,371.29112 +17.5135612,46.8535042,373.82096 +17.5142822,46.8561707,381.47144 +17.5147533,46.8588371,389.97536 +17.5150127,46.8615341,392.048 +17.5151043,46.8642540,387.7808 +17.5149937,46.8670197,386.47016 +17.5147457,46.8698006,382.38584 +17.5141354,46.8726540,385.61672 +17.5128689,46.8753624,390.6764 +17.5106163,46.8777657,399.94232 +17.5071869,46.8793144,401.192 +17.5034218,46.8795586,403.75232 +17.5003281,46.8785019,409.20824 +17.4964581,46.8749237,399.88136 +17.4958000,46.8728714,404.88008 +17.4962807,46.8708153,407.92808 +17.4978256,46.8689423,404.36192 +17.5003300,46.8675194,412.53056 +17.5034332,46.8666725,415.88336 +17.5069084,46.8666458,413.29256 +17.5102272,46.8677826,411.28088 +17.5125103,46.8699722,400.39952 +17.5127735,46.8728333,391.92608 +17.5105896,46.8786736,388.63424 +17.5092926,46.8816147,380.37416 +17.5080719,46.8845634,375.04016 +17.5075550,46.8875809,378.51488 +17.5080776,46.8904305,378.7892 +17.5103817,46.8959274,380.64848 +17.5099659,46.8987846,389.18288 +17.5077763,46.9011421,385.89104 +17.5041962,46.9024925,374.91824 +17.5002937,46.9023895,375.83264 +17.4969807,46.9012718,368.51744 +17.4942493,46.8996620,368.82224 +17.4915791,46.8979874,372.14456 +17.4889145,46.8962975,375.34496 +17.4861851,46.8946152,377.99672 +17.4834881,46.8929596,378.81968 +17.4808350,46.8912888,385.37288 +17.4782314,46.8896027,386.34824 +17.4757252,46.8879356,389.03048 +17.4732456,46.8862419,388.32944 +17.4708214,46.8845482,388.51232 +17.4683647,46.8828278,386.74448 +17.4658203,46.8810616,381.74576 +17.4633369,46.8792381,381.74576 +17.4608116,46.8774757,380.37416 +17.4582958,46.8756828,380.0084 +17.4557571,46.8739128,377.05184 +17.4531918,46.8721313,371.71784 +17.4506474,46.8703613,366.14 +17.4481258,46.8684540,363.61016 +17.4457188,46.8665466,368.36504 +17.4434204,46.8646660,369.52328 +17.4411163,46.8627319,371.41304 +17.4389801,46.8607254,368.60888 +17.4368076,46.8587685,369.67568 +17.4346733,46.8568306,361.68992 +17.4327335,46.8547592,352.24112 +17.4309349,46.8526268,344.1944 +17.4294090,46.8504372,346.328 +17.4284077,46.8482094,347.05952 +17.4278584,46.8459244,343.64576 +17.4275379,46.8436050,337.24496 +17.4271946,46.8412895,334.80656 +17.4268475,46.8390045,332.4596 +17.4266129,46.8367271,334.10552 +17.4264221,46.8344078,335.14184 +17.4261494,46.8320770,337.09256 +17.4258995,46.8297806,338.4032 +17.4257488,46.8275032,340.29296 +17.4255371,46.8252449,341.78648 +17.4253311,46.8229980,344.59064 +17.4251328,46.8207741,348.09584 +17.4249268,46.8185539,348.27872 +17.4246902,46.8163338,344.804 +17.4243851,46.8140831,340.17104 +17.4241524,46.8118401,341.26832 +17.4239349,46.8096008,340.232 +17.4241791,46.8073845,336.2696 +17.4253998,46.8053169,325.05296 +17.4275627,46.8035660,324.65672 +17.4304256,46.8022652,315.75656 +17.4337788,46.8016090,300.94328 +17.4374371,46.8015442,300.97376 +17.4409981,46.8014259,310.72736 +17.4444866,46.8012733,312.92192 +17.4479980,46.8012199,313.50104 +17.4514980,46.8013039,321.6392 +17.4549751,46.8014679,327.24752 +17.4584503,46.8017197,332.36816 +17.4619064,46.8018837,337.45832 +17.4652710,46.8017502,341.20736 +17.4735241,46.7988091,352.54592 +17.4757195,46.7973251,351.8144 +17.4779148,46.7958221,353.00312 +17.4800854,46.7943039,357.3008 +17.4821434,46.7927246,359.25152 +17.4842415,46.7911339,358.27616 +17.4864788,46.7895470,352.02776 +17.4889450,46.7879410,347.51672 +17.4965153,46.7829971,333.61784 +17.4990959,46.7813034,331.97192 +17.5017052,46.7796440,325.66256 +17.5043125,46.7779770,319.658 +17.5069256,46.7763138,318.34736 +17.5095749,46.7746887,314.59832 +17.5122089,46.7730751,310.87976 +17.5148582,46.7714806,307.6184 +17.5174732,46.7698479,303.1988 +17.5224838,46.7664642,303.89984 +17.5248318,46.7646446,305.69816 +17.5271931,46.7628059,310.23968 +17.5295105,46.7609673,308.95952 +17.5317593,46.7590942,310.72736 +17.5374851,46.7564163,314.1716 +17.5447502,46.7561798,296.55416 +17.5485992,46.7567444,284.54504 +17.5523853,46.7576256,285.73376 +17.5559597,46.7585716,311.00168 +17.5592785,46.7596092,323.40704 +17.5625267,46.7607117,319.44464 +17.5657349,46.7618484,325.26632 +17.5689659,46.7630196,319.99328 +17.5722694,46.7640305,318.46928 +17.5755482,46.7652397,318.40832 +17.5788765,46.7664337,313.95824 +17.5822029,46.7676620,314.08016 +17.5854797,46.7688942,313.62296 +17.5886612,46.7701302,318.62168 +17.5917931,46.7713699,326.54648 +17.5949802,46.7725792,320.32856 +17.5982018,46.7738075,316.7624 +17.6014023,46.7750397,317.76824 +17.6045780,46.7762375,319.77992 +17.6078091,46.7774239,322.82792 +17.6111317,46.7786255,313.80584 +17.6144562,46.7798386,312.98288 +17.6177578,46.7810783,317.15864 +17.6209431,46.7823219,320.8772 +17.6240578,46.7835655,320.17616 +17.6273117,46.7848473,318.19496 +17.6305904,46.7861061,318.92648 +17.6339016,46.7873650,318.07304 +17.6372299,46.7886810,323.22416 +17.6403713,46.7898331,357.02648 +17.6432877,46.7906418,397.41248 +17.6491356,46.7924118,396.80288 +17.6520443,46.7933464,415.9748 +17.6574478,46.7953644,438.9872 +17.6602077,46.7965546,444.29072 +17.6631298,46.7976189,452.48984 +17.6660442,46.7985191,475.07552 +17.6687508,46.7996101,487.69424 +17.6714554,46.8008804,484.95104 +17.6744328,46.8020668,480.8972 +17.6774693,46.8033180,490.55936 +17.6804066,46.8046684,492.632 +17.6867905,46.8071175,480.40952 +17.6899662,46.8084221,480.04376 +17.6963539,46.8108673,486.41408 +17.6994858,46.8120728,488.48672 +17.7026062,46.8132896,483.1832 +17.7090969,46.8157272,463.76744 +17.7126179,46.8170013,462.27392 +17.7160606,46.8182068,457.48856 +17.7195663,46.8193932,455.78168 +17.7231464,46.8204041,452.91656 +17.7266541,46.8215103,459.7136 +17.7301064,46.8226814,469.52816 +17.7334042,46.8238792,463.95032 +17.7366543,46.8253136,451.42304 +17.7400494,46.8266907,445.388 +17.7434368,46.8280029,451.08776 +17.7467365,46.8292236,468.67472 +17.7499352,46.8304367,480.40952 +17.7531204,46.8317184,485.34728 +17.7561512,46.8329926,492.69296 +17.7592220,46.8342361,496.47248 +17.7622261,46.8355789,497.204 +17.7652416,46.8369217,491.99192 +17.7684078,46.8382301,482.54312 +17.7715759,46.8396187,487.11512 +17.7746754,46.8410645,488.33432 +17.7779903,46.8423538,477.72728 +17.7813740,46.8437042,461.32904 +17.7847977,46.8451958,446.33288 +17.7882786,46.8466034,445.57088 +17.7917290,46.8478966,449.13704 +17.7950287,46.8493080,451.3316 +17.7982883,46.8507309,450.63056 +17.8016701,46.8520355,449.89904 +17.8050575,46.8533211,447.18632 +17.8083134,46.8547478,449.71616 +17.8115482,46.8561440,455.7512 +17.8148174,46.8573875,466.78496 +17.8180580,46.8586311,473.03336 +17.8211803,46.8600311,474.16112 +17.8243065,46.8613892,470.71688 +17.8275375,46.8627014,467.54696 +17.8340054,46.8652267,470.534 +17.8372135,46.8665657,473.49056 +17.8404961,46.8677864,466.38872 +17.8438625,46.8690987,451.36208 +17.8473206,46.8704948,436.64024 +17.8508720,46.8718338,434.59808 +17.8542881,46.8730965,462.6092 +17.8608494,46.8754387,466.23632 +17.8641701,46.8766479,464.83424 +17.8706017,46.8789253,474.77072 +17.8739128,46.8799515,468.15656 +17.8773365,46.8810425,454.532 +17.8808002,46.8821564,451.72784 +17.8843594,46.8831139,441.18176 +17.8880501,46.8840179,430.02608 +17.8917065,46.8851166,425.33216 +17.8953571,46.8861809,426.58184 +17.8989563,46.8872414,431.33672 +17.9023838,46.8883743,444.65648 +17.9057503,46.8894005,452.27648 +17.9090614,46.8905029,455.294 +17.9120083,46.8920708,475.53272 +17.9147034,46.8937950,489.1268 +17.9172726,46.8956299,493.27208 +17.9197788,46.8974953,496.53344 +17.9221573,46.8994865,487.84664 +17.9243469,46.9017181,458.89064 +17.9287758,46.9065971,410.6408 +17.9309559,46.9090118,386.68352 +17.9331722,46.9115028,362.69576 +17.9355946,46.9139214,339.07376 +17.9382343,46.9162598,317.12816 +17.9410114,46.9185181,293.07944 +17.9439411,46.9205742,276.0716 +17.9472046,46.9222221,263.5748 +17.9506741,46.9232712,261.38024 +17.9541779,46.9237213,266.53136 +17.9576149,46.9237938,272.44448 +17.9611168,46.9239769,278.60144 +17.9645844,46.9247131,292.50032 +17.9678936,46.9258308,303.59504 +17.9711132,46.9269295,323.71184 +17.9742451,46.9279938,337.09256 +17.9773769,46.9290810,350.35136 +17.9804668,46.9301338,369.82808 +17.9834747,46.9311790,390.2192 +17.9864311,46.9322281,407.19656 +17.9893227,46.9333572,419.84576 +17.9922390,46.9344673,431.3672 +17.9951744,46.9355659,440.17592 +17.9981613,46.9367104,440.26736 +18.0012512,46.9379196,438.3776 +18.0044651,46.9391289,432.1292 +18.0077744,46.9403496,428.59352 +18.0111179,46.9415359,427.34384 +18.0145149,46.9426765,418.77896 +18.0179977,46.9437561,418.19984 +18.0215263,46.9443321,439.10912 +18.0246944,46.9440041,461.26808 +18.0272503,46.9428520,460.90232 +18.0289078,46.9411201,457.06184 +18.0305252,46.9393082,455.11112 +18.0321445,46.9375458,449.25896 +18.0336437,46.9356766,443.07152 +18.0353374,46.9339333,439.50536 +18.0371513,46.9321899,443.52872 +18.0389156,46.9304390,448.55792 +18.0405827,46.9287109,449.22848 +18.0420933,46.9269791,448.92368 +18.0434952,46.9252510,449.41136 +18.0448589,46.9235802,449.41136 +18.0461884,46.9219971,445.47944 +18.0474167,46.9204330,438.95672 +18.0485134,46.9189949,444.56504 +18.0494804,46.9176788,441.30368 +18.0504169,46.9163361,428.38016 +18.0514622,46.9149818,420.05912 +18.0526161,46.9136314,413.10968 +18.0537834,46.9122849,405.03248 +18.0549469,46.9109421,400.06424 +18.0560703,46.9095573,394.15112 +18.0572052,46.9081612,390.40208 +18.0583000,46.9067955,391.7432 +18.0593147,46.9054260,387.11024 +18.0602627,46.9040337,384.7328 +18.0612583,46.9026451,382.56872 +18.0622177,46.9012413,375.61928 +18.0643177,46.8984451,360.83648 +18.0654469,46.8970604,349.9856 +18.0665493,46.8956604,343.4324 +18.0676155,46.8942451,333.13016 +18.0686398,46.8927727,325.4492 +18.0696335,46.8913040,323.34608 +18.0707111,46.8898849,322.0964 +18.0717659,46.8884926,317.12816 +18.0727959,46.8871193,302.4368 +18.0737572,46.8857880,289.57424 +18.0746880,46.8845139,277.71752 +18.0756435,46.8832817,264.36728 +18.0766811,46.8820381,246.07928 +18.0786877,46.8793221,234.22256 +18.0816574,46.8753128,238.2764 +18.0826950,46.8740540,232.66808 +18.0838928,46.8727722,219.74456 +18.0850239,46.8713608,208.31456 +18.0861454,46.8699532,199.14008 +18.0872345,46.8685493,188.04536 +18.0882187,46.8671799,173.6588 +18.0891972,46.8658905,157.6568 +18.0911446,46.8633881,139.09448 +18.0933037,46.8606148,136.1684 +18.0937729,46.8600426,135.92456 +18.0940208,46.8597984,135.68072 +18.0940857,46.8597450,135.80264 +18.0940342,46.8597260,135.7112 +18.0939217,46.8597565,135.68072 +18.0938206,46.8598213,135.61976 +18.0937138,46.8598824,135.58928 +18.0936165,46.8599396,135.61976 +18.0935078,46.8600006,135.52832 +18.0931339,46.8599701,135.19304 +18.0928745,46.8598747,134.91872 +18.0925999,46.8597755,134.70536 +18.0923386,46.8597527,134.61392 +18.0921459,46.8598442,134.61392 +18.0920258,46.8599739,134.55296 +18.0919247,46.8601074,134.70536 +18.0918198,46.8602371,134.76632 +18.0916862,46.8603897,134.6444 +18.0915470,46.8605537,134.6444 +18.0914097,46.8607254,134.9492 +18.0911369,46.8610649,135.16256 +18.0910034,46.8612518,135.13208 +18.0908546,46.8614349,135.4064 +18.0906982,46.8616295,135.68072 +18.0905457,46.8618240,135.80264 +18.0903912,46.8620148,136.016 +18.0900574,46.8624229,136.3208 +18.0898876,46.8626099,136.56464 +18.0897503,46.8627892,136.9304 +18.0895233,46.8628502,136.80848 +18.0892868,46.8627663,136.50368 +18.0890694,46.8627472,136.25984 +18.0889435,46.8628159,136.4732 +18.0888538,46.8628731,136.29032 +18.0887642,46.8629265,136.41224 +18.0886879,46.8629951,136.41224 +18.0886784,46.8630028,136.4732 +18.0886784,46.8630028,136.38176 +18.0886784,46.8630028,136.3208 + + + + + diff --git a/Source/Core/WallGeometry.js b/Source/Core/WallGeometry.js new file mode 100644 index 000000000000..79ed43f48d85 --- /dev/null +++ b/Source/Core/WallGeometry.js @@ -0,0 +1,285 @@ +/*global define*/ +define([ + './DeveloperError', + './Cartesian3', + './Cartographic', + './Ellipsoid', + './Math', + './Matrix4', + './ComponentDatatype', + './PrimitiveType', + './defaultValue', + './BoundingSphere', + './GeometryAttribute', + './GeometryIndices', + '../Scene/sampleTerrain', + '../ThirdParty/when' + ], function( + DeveloperError, + Cartesian3, + Cartographic, + Ellipsoid, + Math, + Matrix4, + ComponentDatatype, + PrimitiveType, + defaultValue, + BoundingSphere, + GeometryAttribute, + GeometryIndices, + sampleTerrain, + when) { + "use strict"; + + /** + * Creates a wall, which is similar to a line string. A wall is defined by a series of points, + * which extrude down to the ground. Optionally they can extrude downwards to a specified height. + * The points in the wall can be offset by supplied terrain elevation data. + * + * @alias WallGeometry + * @constructor + * + * @param {array of Cartographic} coordinates an array of Cartographic objects, which are the coordinates of the wall + * @param {string} altitudeMode either 'absolute' or 'relativeToGround'. 'absolute' means the height + * is treated from the WGS84 ellipsoid. 'relativeToGround' means they are treated + * relative to the supplied terrain data + * @param {array of Cartographic} [terrain] requred if altitudeMode is 'relativeToGround'. has to denote the same points + * as in coordinates, with the ground elevation in the height property of each point + * @param {number} [top] optional, the top of the wall. if specified, the top of the wall is treated as this + * height, and the information in the coordinates array is disregarded + * @param {number} [bottom] optional, the bottom of the wall. if specified, the bottom of the wall is treated as + * this height. otherwise its treated as 'ground' (the WGS84 ellipsoid height 0) + * @param {object} [pickData] the geometry pick data + * + * @exception {DeveloperError} All dimensions components must be greater than or equal to zero. + */ + var WallGeometry = function(options) { + options = defaultValue(options, defaultValue.EMPTY_OBJECT); + + var coordinates; + + if (typeof options.coordinates !== 'undefined') { + coordinates = options.coordinates; + } else { + throw new DeveloperError('Coordinates must be supplied.'); + } + + var attributes = {}; + var indexLists = []; + + if (options.altitudeMode === 'relativeToGround' && typeof options.terrain === 'undefined') { + throw new DeveloperError('No terrain supplied when required.'); + } + if (typeof options.terrain !== 'undefined' && options.terrain.length !== options.coordinates.length) { + throw new DeveloperError('Coordinates and terrain points don\'t match in number'); + } + + var c = new Cartographic(); + var ellipsoid = Ellipsoid.WGS84; + + attributes.position = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : [] + }); + + // add lower and upper points one after the other, lower + // points being even and upper points being odd + for (var i = 0; i < options.coordinates.length; ++i) { + c = Cartographic.clone(options.coordinates[i]); + c.height = 0; + if (options.bottom !== undefined) { + c.height = options.bottom; + } + if (options.terrain !== undefined && options.bottom !== undefined && + !isNaN(options.terrain[i].height)) { + + c.height += options.terrain[i].height; + } + var v = ellipsoid.cartographicToCartesian(c); + + // insert the lower point + attributes.position.values.push(v.x); + attributes.position.values.push(v.y); + attributes.position.values.push(v.z); + + // get the original height back, or set the top value + c.height = options.top === undefined ? options.coordinates[i].height + : options.top; + if (options.terrain !== undefined && !isNaN(options.terrain[i].height)) { + c.height += options.terrain[i].height; + } + v = ellipsoid.cartographicToCartesian(c); + + // insert the upper point + attributes.position.values.push(v.x); + attributes.position.values.push(v.y); + attributes.position.values.push(v.z); + } + + indexLists.push( + new GeometryIndices({ + primitiveType : PrimitiveType.TRIANGLES, + values : [] + })); + + + // prepare the side walls, two triangles for each wall + // + // A (i+1) B (i+3) E + // +--------+-------+ + // | / | /| triangles: A C B + // | / | / | B C D + // | / | / | + // | / | / | + // | / | / | + // | / | / | + // +--------+-------+ + // C (i) D (i+2) F + // + + var noPoints1 = attributes.position.values.length / 3 - 2; + var indexes = indexLists[0].values; + for (i = 0; i < noPoints1; i += 2) { + + // first do A C B + indexes.push(i + 1); + indexes.push(i); + indexes.push(i + 3); + + // now do B C D + indexes.push(i + 3); + indexes.push(i); + indexes.push(i + 2); + } + + /** + * The ellipsoid used to convert from cartographic to cartesian + */ + this.ellipsoid = ellipsoid; + + /** + * The attributes (vertices) + */ + this.attributes = attributes; + + /** + * The indexes used for GL rendering + */ + this.indexLists = indexLists; + + /** + * The bounding sphere for the whole geometry + */ + this.boundingSphere = new BoundingSphere.fromVertices(attributes.position.values); + + /** + * The model matrix, simply the identity + */ + this.modelMatrix = defaultValue(options.modelMatrix, Matrix4.IDENTITY.clone()); + + /** + * Pick data used for selection + */ + this.pickData = options.pickData; + }; + + // default KML namespace resolver, see + // https://developer.mozilla.org/en-US/docs/Introduction_to_using_XPath_in_JavaScript#Implementing_a_User_Defined_Namespace_Resolver + function kmlNsResolver(prefix) { + return 'http://www.opengis.net/kml/2.2'; + } + + /** + * Create a set of Walls from a KML document that includes LineString elements. + * + * @param {DOM node} kmlNode the KML documents document node + * @param {CesiumTerrainProvider} terrainProvider an optional terrain provider for LineStrings that need + * a ground reference. + * @param {function(wall)} callback a function that will receive each WallGeometry created, one at a time. + */ + WallGeometry.fromKML = function kmlReqListener(kmlNode, terrainProvider, callback) { + var name = kmlNode.evaluate('//kml:name', kmlNode, kmlNsResolver, + XPathResult.STRING_TYPE, null); + + var it = kmlNode.evaluate('//kml:LineString', kmlNode, kmlNsResolver, + XPathResult.UNORDERED_NODE_ITERATOR_TYPE, null); + + var addNameToWall = function(wall) { + wall.pickData = name; + callback(wall); + }; + + for (var node = it.iterateNext(); node; node = it.iterateNext()) { + WallGeometry.fromKMLLineString(node, terrainProvider, addNameToWall); + } + }; + + /** + * Create a Wall from a KML LineString DOM element. + * + * @param {DOM node} lineString the KML LineString DOM node to build this Wall from. + * @param {CesiumTerrainProvider} [terrainProvider] an optional terrain provider, used when relative-to-ground elevation + * data is needed to render the wall + * @param {function(wall)} callback the callback that will be called with the created WallGeometry + */ + WallGeometry.fromKMLLineString = function(lineString, terrainProvider, callback) { + var altitudeMode; + var coordinates = []; + + var doc = lineString.ownerDocument; + + // get the coordinates + var xpResult = doc.evaluate('kml:coordinates/text()', lineString, kmlNsResolver, + XPathResult.STRING_TYPE, null); + var coordString = xpResult.stringValue; + var coordSplitWs = coordString.split(/[\s]/); + for (var i = 0; i < coordSplitWs.length; ++i) { + var coordLine = coordSplitWs[i]; + + if (!coordLine.trim()) { + continue; + } + var coordSplit = coordLine.split(','); + + var c = new Cartographic(Math.toRadians(parseFloat(coordSplit[0])), + Math.toRadians(parseFloat(coordSplit[1])), + coordSplit.length < 3 ? 0 : parseFloat(coordSplit[2])); + coordinates.push(c); + } + + // get the altitudeMode flag + xpResult = doc.evaluate('kml:altitudeMode/text()', lineString, kmlNsResolver, + XPathResult.STRING_TYPE, null); + altitudeMode = xpResult.stringValue; + + var options = { + altitudeMode : altitudeMode, + coordinates : coordinates + }; + + if (altitudeMode === 'relativeToGround') { + // request the terrain data for each point of the line string + var coords = []; + + for (i = 0; i < options.coordinates.length; ++i) { + coords.push(Cartographic.clone(options.coordinates[i])); + } + + // request the elevation ground data + when(sampleTerrain(terrainProvider, 11, coords), function(positions) { + options.terrain = positions; + + var wall = new WallGeometry(options); + callback(wall); + }); + } else { + // just create a Wall and return it + var wall = new WallGeometry(options); + callback(wall); + } + }; + + return WallGeometry; +}); + diff --git a/Specs/Core/WallGeometrySpec.js b/Specs/Core/WallGeometrySpec.js new file mode 100644 index 000000000000..7f84a8a072d5 --- /dev/null +++ b/Specs/Core/WallGeometrySpec.js @@ -0,0 +1,70 @@ +/*global defineSuite*/ +defineSuite([ + 'Core/WallGeometry', + 'Core/Cartographic' + ], function( + WallGeometry, + Cartographic) { + "use strict"; + /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/ + + it('create with no parameters', function() { + expect(function() { + return new WallGeometry({ + }); + }).toThrow(); + }); + + it('create simple absolute', function() { + var coords = [ + new Cartographic(49, 18, 1000), + new Cartographic(50, 18, 1000) + ]; + + var w = new WallGeometry({ + altitudeMode : 'absolute', + coordinates : coords + }); + + expect(w.attributes.position.values.length).toEqual(2 * 2 * 3); + expect(w.indexLists[0].values.length).toEqual(2 * 3); + }); + + it('create relative to ground no terrain', function() { + var coords = [ + new Cartographic(49, 18, 1000), + new Cartographic(50, 18, 1000) + ]; + + // this will throw an exception, as no terrain is specified + expect(function() { + return new WallGeometry({ + altitudeMode : 'relativeToGround', + coordinates : coords + }).toThrow(); + }); + }); + + it('create relative to ground', function() { + var coords = [ + new Cartographic(49, 18, 1000), + new Cartographic(50, 18, 1000) + ]; + + var terrain = [ + new Cartographic(49, 18, 100), + new Cartographic(50, 18, 110) + ]; + + var w = new WallGeometry({ + altitudeMode : 'relativeToGround', + coordinates : coords, + terrain : terrain + }); + + expect(w.attributes.position.values.length).toEqual(2 * 2 * 3); + expect(w.indexLists[0].values.length).toEqual(2 * 3); + }); + +}); + From a86461261c48b99375b24d6463666a66fe652bf7 Mon Sep 17 00:00:00 2001 From: hpinkos Date: Tue, 21 May 2013 14:34:12 -0400 Subject: [PATCH 050/306] minor changes to documentation and variables --- Source/Core/GeometryFilters.js | 40 +++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/Source/Core/GeometryFilters.js b/Source/Core/GeometryFilters.js index d5da941b66f6..308280e1b22a 100644 --- a/Source/Core/GeometryFilters.js +++ b/Source/Core/GeometryFilters.js @@ -848,6 +848,7 @@ define([ * @returns The modified mesh argument. * * @exception {DeveloperError} mesh.attributes.position.values is required + * @exception {DeveloperError} mesh.attributes.position.values.length must be a multiple of 3 * * @example * mesh = GeometryFilters.computeNormals(mesh); @@ -887,7 +888,7 @@ define([ var numIndices = indices.length; var normalsPerVertex = new Array(numVertices); var normalsPerTriangle = new Array(numIndices/3); - var normalIndices = new Array(numVertices); + var normalIndices = new Array(numIndices); for (var i = 0; i < numVertices; i++) { normalsPerVertex[i] = { @@ -902,16 +903,19 @@ define([ var i0 = indices[i]; var i1 = indices[i+1]; var i2 = indices[i+2]; - - v0.x = vertices[i0*3]; - v0.y = vertices[i0*3+1]; - v0.z = vertices[i0*3+2]; - v1.x = vertices[i1*3]; - v1.y = vertices[i1*3+1]; - v1.z = vertices[i1*3+2]; - v2.x = vertices[i2*3]; - v2.y = vertices[i2*3+1]; - v2.z = vertices[i2*3+2]; + var i03 = i0*3; + var i13 = i1*3; + var i23 = i2*3; + + v0.x = vertices[i03]; + v0.y = vertices[i03+1]; + v0.z = vertices[i03+2]; + v1.x = vertices[i13]; + v1.y = vertices[i13+1]; + v1.z = vertices[i13+2]; + v2.x = vertices[i23]; + v2.y = vertices[i23+1]; + v2.z = vertices[i23+2]; normalsPerVertex[i0].count++; normalsPerVertex[i1].count++; @@ -957,7 +961,9 @@ define([ values: new Array(numVertices * 3) }); } + var normalValues = mesh.attributes.normal.values; for (i = 0; i < numVertices; i++) { + var i3 = i * 3; vertexNormalData = normalsPerVertex[i]; if (vertexNormalData.count > 0) { Cartesian3.ZERO.clone(normal); @@ -965,13 +971,13 @@ define([ normal.add(normalsPerTriangle[normalIndices[vertexNormalData.indexOffset + j]], normal); } normal.normalize(normal); - mesh.attributes.normal.values[3*i] = normal.x; - mesh.attributes.normal.values[3*i+1] = normal.y; - mesh.attributes.normal.values[3*i+2] = normal.z; + normalValues[i3] = normal.x; + normalValues[i3+1] = normal.y; + normalValues[i3+2] = normal.z; } else { - mesh.attributes.normal.values[3*i] = 0; - mesh.attributes.normal.values[3*i+1] = 0; - mesh.attributes.normal.values[3*i+2] = 1; + normalValues[i3] = 0; + normalValues[i3+1] = 0; + normalValues[i3+2] = 1; } } } From 260d6cf23c61467aaeedb677f8c3ba32d23c4f7e Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Tue, 21 May 2013 16:04:52 -0400 Subject: [PATCH 051/306] Fix JSHint warnings --- Source/Core/Geometry.js | 2 +- Source/Core/GeometryFilters.js | 23 +++++++++++++---------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/Source/Core/Geometry.js b/Source/Core/Geometry.js index 404ef90b7bae..4dada281fa35 100644 --- a/Source/Core/Geometry.js +++ b/Source/Core/Geometry.js @@ -2,7 +2,7 @@ define([ './defaultValue', './DeveloperError', - './Matrix4', + './Matrix4' ], function( defaultValue, DeveloperError, diff --git a/Source/Core/GeometryFilters.js b/Source/Core/GeometryFilters.js index 308280e1b22a..d6a857853684 100644 --- a/Source/Core/GeometryFilters.js +++ b/Source/Core/GeometryFilters.js @@ -714,6 +714,9 @@ define([ // Find subset of attributes in all meshes var attributes = findAttributesInAllMeshes(meshes); + var values; + var sourceValues; + var sourceValuesLength; // PERFORMANCE_IDEA: Interleave here instead of createVertexArrayFromMesh to save a copy. // This will require adding offset and stride to the mesh. @@ -721,12 +724,12 @@ define([ // Combine attributes from each mesh into a single typed array for (name in attributes) { if (attributes.hasOwnProperty(name)) { - var values = attributes[name].values; + values = attributes[name].values; k = 0; for (i = 0; i < length; ++i) { - var sourceValues = meshes[i].attributes[name].values; - var sourceValuesLength = sourceValues.length; + sourceValues = meshes[i].attributes[name].values; + sourceValuesLength = sourceValues.length; for (j = 0; j < sourceValuesLength; ++j) { values[k++] = sourceValues[j]; @@ -791,17 +794,17 @@ define([ indexListsLength = indexLists.length; for (j = 0; j < indexListsLength; ++j) { - var indices = indexLists[j]; - var sourceValues = indices.values; - var sourceValuesLength = sourceValues.length; + indices = indexLists[j]; + sourceValues = indices.values; + sourceValuesLength = sourceValues.length; var destValues = indexListsByPrimitiveType[indices.primitiveType].values; - var m = indexListsByPrimitiveType[indices.primitiveType].currentOffset; + var n = indexListsByPrimitiveType[indices.primitiveType].currentOffset; for (k = 0; k < sourceValuesLength; ++k) { - destValues[m++] = offset + sourceValues[k]; + destValues[n++] = offset + sourceValues[k]; } - indexListsByPrimitiveType[indices.primitiveType].currentOffset = m; + indexListsByPrimitiveType[indices.primitiveType].currentOffset = n; } var attrs = meshes[i].attributes; @@ -814,7 +817,7 @@ define([ } // Create bounding sphere that includes all meshes - var boundingSphere = undefined; + var boundingSphere; for (i = 0; i < length; ++i) { var bs = meshes[i].boundingSphere; From 72c4d92555148bf3148d3509610186c9cffb23d4 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Tue, 21 May 2013 16:20:47 -0400 Subject: [PATCH 052/306] Updates based on review. --- Source/Core/EllipsoidGeometry.js | 194 ++++++++++++++++--------------- 1 file changed, 100 insertions(+), 94 deletions(-) diff --git a/Source/Core/EllipsoidGeometry.js b/Source/Core/EllipsoidGeometry.js index ab9d97f3c083..d14fe63f1ca5 100644 --- a/Source/Core/EllipsoidGeometry.js +++ b/Source/Core/EllipsoidGeometry.js @@ -27,6 +27,88 @@ define([ VertexFormat) { "use strict"; + var scratchDirection = new Cartesian3(); + + function addEdgePositions(i0, i1, numberOfPartitions, positions) { + var indices = []; + indices[0] = i0; + indices[2 + (numberOfPartitions - 1) - 1] = i1; + + var origin = positions[i0]; + var direction = Cartesian3.subtract(positions[i1], positions[i0], scratchDirection); + + for ( var i = 1; i < numberOfPartitions; ++i) { + var delta = i / numberOfPartitions; + var position = Cartesian3.multiplyByScalar(direction, delta); + Cartesian3.add(origin, position, position); + + indices[i] = positions.length; + positions.push(position); + } + + return indices; + } + + var scratchX = new Cartesian3(); + var scratchY = new Cartesian3(); + var scratchOffsetX = new Cartesian3(); + var scratchOffsetY = new Cartesian3(); + + function addFaceTriangles(leftBottomToTop, bottomLeftToRight, rightBottomToTop, topLeftToRight, numberOfPartitions, positions, indices) { + var origin = positions[bottomLeftToRight[0]]; + var x = Cartesian3.subtract(positions[bottomLeftToRight[bottomLeftToRight.length - 1]], origin, scratchX); + var y = Cartesian3.subtract(positions[topLeftToRight[0]], origin, scratchY); + + var bottomIndicesBuffer = []; + var topIndicesBuffer = []; + + var bottomIndices = bottomLeftToRight; + var topIndices = topIndicesBuffer; + + for ( var j = 1; j <= numberOfPartitions; ++j) { + if (j !== numberOfPartitions) { + if (j !== 1) { + // + // This copy could be avoided by ping ponging buffers. + // + bottomIndicesBuffer = topIndicesBuffer.slice(0); + bottomIndices = bottomIndicesBuffer; + } + + topIndicesBuffer[0] = leftBottomToTop[j]; + topIndicesBuffer[numberOfPartitions] = rightBottomToTop[j]; + + var deltaY = j / numberOfPartitions; + var offsetY = Cartesian3.multiplyByScalar(y, deltaY, scratchOffsetY); + + for ( var i = 1; i < numberOfPartitions; ++i) { + var deltaX = i / numberOfPartitions; + var offsetX = Cartesian3.multiplyByScalar(x, deltaX, scratchOffsetX); + var position = Cartesian3.add(origin, offsetX); + Cartesian3.add(position, offsetY, position); + + topIndicesBuffer[i] = positions.length; + positions.push(position); + } + } else { + if (j !== 1) { + bottomIndices = topIndicesBuffer; + } + topIndices = topLeftToRight; + } + + for ( var k = 0; k < numberOfPartitions; ++k) { + indices.push(bottomIndices[k]); + indices.push(bottomIndices[k + 1]); + indices.push(topIndices[k + 1]); + + indices.push(bottomIndices[k]); + indices.push(topIndices[k + 1]); + indices.push(topIndices[k]); + } + } + } + var sphericalNormal = new Cartesian3(); var normal = new Cartesian3(); var tangent = new Cartesian3(); @@ -174,26 +256,32 @@ define([ } if (vertexFormat.normal || vertexFormat.tangent || vertexFormat.binormal) { - var normals = new Array(length * 3); - var tangents = new Array(length * 3); - var binormals = new Array(length * 3); + var normals = (vertexFormat.normal) ? new Array(length * 3) : undefined; + var tangents = (vertexFormat.tangent) ? new Array(length * 3) : undefined; + var binormals = (vertexFormat.binormal) ? new Array(length * 3) : undefined; for (i = j = 0; i < length; ++i, j += 3) { ellipsoid.geodeticSurfaceNormal(positions[i], normal); Cartesian3.cross(Cartesian3.UNIT_Z, normal, tangent); Cartesian3.cross(tangent, normal, binormal); - normals[j] = normal.x; - normals[j + 1] = normal.y; - normals[j + 2] = normal.z; + if (vertexFormat.normal) { + normals[j] = normal.x; + normals[j + 1] = normal.y; + normals[j + 2] = normal.z; + } - tangents[j] = tangent.x; - tangents[j + 1] = tangent.y; - tangents[j + 2] = tangent.z; + if (vertexFormat.tangent) { + tangents[j] = tangent.x; + tangents[j + 1] = tangent.y; + tangents[j + 2] = tangent.z; + } - binormals[j] = binormal.x; - binormals[j + 1] = binormal.y; - binormals[j + 2] = binormal.z; + if (vertexFormat.binormal) { + binormals[j] = binormal.x; + binormals[j + 1] = binormal.y; + binormals[j + 2] = binormal.z; + } } if (vertexFormat.normal) { @@ -266,87 +354,5 @@ define([ this.pickData = options.pickData; }; - var scratchDirection = new Cartesian3(); - - function addEdgePositions(i0, i1, numberOfPartitions, positions) { - var indices = []; - indices[0] = i0; - indices[2 + (numberOfPartitions - 1) - 1] = i1; - - var origin = positions[i0]; - var direction = Cartesian3.subtract(positions[i1], positions[i0], scratchDirection); - - for ( var i = 1; i < numberOfPartitions; ++i) { - var delta = i / numberOfPartitions; - var position = Cartesian3.multiplyByScalar(direction, delta); - Cartesian3.add(origin, position, position); - - indices[i] = positions.length; - positions.push(position); - } - - return indices; - } - - var scratchX = new Cartesian3(); - var scratchY = new Cartesian3(); - var scratchOffsetX = new Cartesian3(); - var scratchOffsetY = new Cartesian3(); - - function addFaceTriangles(leftBottomToTop, bottomLeftToRight, rightBottomToTop, topLeftToRight, numberOfPartitions, positions, indices) { - var origin = positions[bottomLeftToRight[0]]; - var x = Cartesian3.subtract(positions[bottomLeftToRight[bottomLeftToRight.length - 1]], origin, scratchX); - var y = Cartesian3.subtract(positions[topLeftToRight[0]], origin, scratchY); - - var bottomIndicesBuffer = []; - var topIndicesBuffer = []; - - var bottomIndices = bottomLeftToRight; - var topIndices = topIndicesBuffer; - - for ( var j = 1; j <= numberOfPartitions; ++j) { - if (j !== numberOfPartitions) { - if (j !== 1) { - // - // This copy could be avoided by ping ponging buffers. - // - bottomIndicesBuffer = topIndicesBuffer.slice(0); - bottomIndices = bottomIndicesBuffer; - } - - topIndicesBuffer[0] = leftBottomToTop[j]; - topIndicesBuffer[numberOfPartitions] = rightBottomToTop[j]; - - var deltaY = j / numberOfPartitions; - var offsetY = Cartesian3.multiplyByScalar(y, deltaY, scratchOffsetY); - - for ( var i = 1; i < numberOfPartitions; ++i) { - var deltaX = i / numberOfPartitions; - var offsetX = Cartesian3.multiplyByScalar(x, deltaX, scratchOffsetX); - var position = Cartesian3.add(origin, offsetX); - Cartesian3.add(position, offsetY, position); - - topIndicesBuffer[i] = positions.length; - positions.push(position); - } - } else { - if (j !== 1) { - bottomIndices = topIndicesBuffer; - } - topIndices = topLeftToRight; - } - - for ( var k = 0; k < numberOfPartitions; ++k) { - indices.push(bottomIndices[k]); - indices.push(bottomIndices[k + 1]); - indices.push(topIndices[k + 1]); - - indices.push(bottomIndices[k]); - indices.push(topIndices[k + 1]); - indices.push(topIndices[k]); - } - } - } - return EllipsoidGeometry; }); \ No newline at end of file From 4c988158b4d0e0860dcaa272ca1b87694543071a Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Tue, 21 May 2013 16:21:23 -0400 Subject: [PATCH 053/306] Added Akos Maroy to CONTRIBUTORS.md --- CONTRIBUTORS.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index be4800db558b..dea1f3b9a592 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -19,6 +19,8 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for details on how to contribute to Cesiu * [Hannah Pinkos](https://github.com/hpinkos) * [NICTA](http://www.nicta.com.au/) * [Chris Cooper](https://github.com/chris-cooper) +* [EU Edge](http://euedge.com/) + * [Ákos Maróy](https://github.com/akosmaroy) ## [Individual CLA](http://www.agi.com/licenses/individual-cla-agi-v1.0.txt) * [Victor Berchet](https://github.com/vicb) From 3aa6874538c20eaf90a3f4e0217fe8f53aa1f588 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Tue, 21 May 2013 16:31:06 -0400 Subject: [PATCH 054/306] CHANGES.md tweaks --- CHANGES.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 1950cb6c2c10..6cd746244c04 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -17,10 +17,11 @@ Beta Releases * Replaced `Uniform.getFrameNumber` and `Uniform.getTime` with `Uniform.getFrameState`, which returns the full frame state. * Improved the performance of drawing polygons created with `configureFromPolygonHierarchy`. * Added `GeometryFilters.combine` to combine meshes for better batching. +* Added `GeometryFilters.computeNormals` to find the normals of vertices in a mesh. * Added `BoundingSphere.fromEllipsoid`. * Added renderer support for `OES_element_index_uint`, which can improve performance by reducing batch sizes. * Added 'czm_tangentToEyeSpaceMatrix` built-in GLSL function. -* Added `GeometryFilters.computeNormals` to find the normals of vertices in a mesh. + ### b17 - 2013-06-03 * Breaking changes: From 30319aebf97eaf6878d3ef939b9fda6566a2d212 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Tue, 21 May 2013 17:31:40 -0300 Subject: [PATCH 055/306] Another CHANGES.md tweak --- CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 6cd746244c04..fc56081429c4 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -20,7 +20,7 @@ Beta Releases * Added `GeometryFilters.computeNormals` to find the normals of vertices in a mesh. * Added `BoundingSphere.fromEllipsoid`. * Added renderer support for `OES_element_index_uint`, which can improve performance by reducing batch sizes. -* Added 'czm_tangentToEyeSpaceMatrix` built-in GLSL function. +* Added `czm_tangentToEyeSpaceMatrix` built-in GLSL function. ### b17 - 2013-06-03 From 689f620073c17f9cfb8d05c171ec20966f9997e5 Mon Sep 17 00:00:00 2001 From: Akos Maroy Date: Wed, 22 May 2013 11:23:48 +0200 Subject: [PATCH 056/306] added WallGeometry comment into CHANGES.md --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index fc56081429c4..99856943fcaf 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -21,6 +21,7 @@ Beta Releases * Added `BoundingSphere.fromEllipsoid`. * Added renderer support for `OES_element_index_uint`, which can improve performance by reducing batch sizes. * Added `czm_tangentToEyeSpaceMatrix` built-in GLSL function. +* Added WallGeometry ### b17 - 2013-06-03 From 2a5f325275a131872bc907f2fe0a34a9e3e2b820 Mon Sep 17 00:00:00 2001 From: Akos Maroy Date: Wed, 22 May 2013 13:51:42 +0200 Subject: [PATCH 057/306] added PolygonGeometry --- Apps/Sandcastle/gallery/Polygons.html | 193 ++++++++++------ CHANGES.md | 1 + Source/Core/PolygonGeometry.js | 317 ++++++++++++++++++++++++++ Specs/Core/PolygonGeometrySpec.js | 284 +++++++++++++++++++++++ 4 files changed, 722 insertions(+), 73 deletions(-) create mode 100644 Source/Core/PolygonGeometry.js create mode 100644 Specs/Core/PolygonGeometrySpec.js diff --git a/Apps/Sandcastle/gallery/Polygons.html b/Apps/Sandcastle/gallery/Polygons.html index e6ea7dfbd65d..14769239701b 100644 --- a/Apps/Sandcastle/gallery/Polygons.html +++ b/Apps/Sandcastle/gallery/Polygons.html @@ -36,103 +36,150 @@ { "use strict"; + function createAppearance(color) { + var material = Cesium.Material.fromType(undefined, Cesium.Material.ColorType); + material.uniforms.color = color; + var appearance = new Cesium.Appearance({ + renderState : { + cull : { + enabled : false + }, + depthTest : { + enabled : true + }, + depthMask : false, + blending : Cesium.BlendingState.ALPHA_BLEND + }, + material : material + }); + + return appearance; + } + function createPrimitives(widget) { var scene = widget.scene; var ellipsoid = widget.centralBody.getEllipsoid(); var primitives = scene.getPrimitives(); // Create a simple polygon - var polygon = new Cesium.Polygon(); - Sandcastle.declare(polygon); // For highlighting on mouseover in Sandcastle. - polygon.setPositions(ellipsoid.cartographicArrayToCartesianArray([ - Cesium.Cartographic.fromDegrees(-72.0, 40.0), - Cesium.Cartographic.fromDegrees(-70.0, 35.0), - Cesium.Cartographic.fromDegrees(-75.0, 30.0), - Cesium.Cartographic.fromDegrees(-70.0, 30.0), - Cesium.Cartographic.fromDegrees(-68.0, 40.0) - ])); - primitives.add(polygon); - - polygon = new Cesium.Polygon(); - Sandcastle.declare(polygon); - polygon.configureExtent(new Cesium.Extent( - Cesium.Math.toRadians(-110.0), - Cesium.Math.toRadians(0.0), - Cesium.Math.toRadians(-90.0), - Cesium.Math.toRadians(20.0)), - 0.0, Cesium.Math.toRadians(45)); - polygon.material = Cesium.Material.fromType(scene.getContext(), Cesium.Material.ColorType); - polygon.material.uniforms.color = {red: 1.0, green: 0.0, blue: 1.0, alpha: 0.75}; - primitives.add(polygon); + var polygon = new Cesium.PolygonGeometry({ + positions : ellipsoid.cartographicArrayToCartesianArray([ + Cesium.Cartographic.fromDegrees(-72.0, 40.0), + Cesium.Cartographic.fromDegrees(-70.0, 35.0), + Cesium.Cartographic.fromDegrees(-75.0, 30.0), + Cesium.Cartographic.fromDegrees(-70.0, 30.0), + Cesium.Cartographic.fromDegrees(-68.0, 40.0) + ]), + pickData : 'polygon1' + }); + + var primitive = new Cesium.Primitive({ + geometries : [ polygon ], + appearance : createAppearance(new Cesium.Color(1.0, 1.0, 0.0, 0.75)) + }); + primitives.add(primitive); + + // create a polygon from an extent with rotation + polygon = new Cesium.PolygonGeometry({ + extent : new Cesium.Extent(Cesium.Math.toRadians(-110.0), + Cesium.Math.toRadians(0.0), + Cesium.Math.toRadians(-90.0), + Cesium.Math.toRadians(20.0)), + height : 0.0, + rotation : Cesium.Math.toRadians(45), + pickData : 'polygon2' + }); + + primitive = new Cesium.Primitive({ + geometries : [ polygon ], + appearance : createAppearance({red: 1.0, green: 0.0, blue: 1.0, alpha: 0.75}) + }); + primitives.add(primitive); // Create a nested polygon with holes - var polygonHierarchy = new Cesium.Polygon(); - Sandcastle.declare(polygonHierarchy); // For highlighting on mouseover in Sandcastle. - - var hierarchy = { - positions : ellipsoid.cartographicArrayToCartesianArray( - [ - Cesium.Cartographic.fromDegrees(-109.0, 30.0), - Cesium.Cartographic.fromDegrees(-95.0, 30.0), - Cesium.Cartographic.fromDegrees(-95.0, 40.0), - Cesium.Cartographic.fromDegrees(-109.0, 40.0) - ]), - holes : [{ + polygon = new Cesium.PolygonGeometry({ + polygonHierarchy : { positions : ellipsoid.cartographicArrayToCartesianArray( [ - Cesium.Cartographic.fromDegrees(-107.0, 31.0), - Cesium.Cartographic.fromDegrees(-107.0, 39.0), - Cesium.Cartographic.fromDegrees(-97.0, 39.0), - Cesium.Cartographic.fromDegrees(-97.0, 31.0) + Cesium.Cartographic.fromDegrees(-109.0, 30.0), + Cesium.Cartographic.fromDegrees(-95.0, 30.0), + Cesium.Cartographic.fromDegrees(-95.0, 40.0), + Cesium.Cartographic.fromDegrees(-109.0, 40.0) ]), holes : [{ positions : ellipsoid.cartographicArrayToCartesianArray( [ - Cesium.Cartographic.fromDegrees(-105.0, 33.0), - Cesium.Cartographic.fromDegrees(-99.0, 33.0), - Cesium.Cartographic.fromDegrees(-99.0, 37.0), - Cesium.Cartographic.fromDegrees(-105.0, 37.0) + Cesium.Cartographic.fromDegrees(-107.0, 31.0), + Cesium.Cartographic.fromDegrees(-107.0, 39.0), + Cesium.Cartographic.fromDegrees(-97.0, 39.0), + Cesium.Cartographic.fromDegrees(-97.0, 31.0) ]), holes : [{ positions : ellipsoid.cartographicArrayToCartesianArray( [ - Cesium.Cartographic.fromDegrees(-103.0, 34.0), - Cesium.Cartographic.fromDegrees(-101.0, 34.0), - Cesium.Cartographic.fromDegrees(-101.0, 36.0), - Cesium.Cartographic.fromDegrees(-103.0, 36.0) - ]) + Cesium.Cartographic.fromDegrees(-105.0, 33.0), + Cesium.Cartographic.fromDegrees(-99.0, 33.0), + Cesium.Cartographic.fromDegrees(-99.0, 37.0), + Cesium.Cartographic.fromDegrees(-105.0, 37.0) + ]), + holes : [{ + positions : ellipsoid.cartographicArrayToCartesianArray( + [ + Cesium.Cartographic.fromDegrees(-103.0, 34.0), + Cesium.Cartographic.fromDegrees(-101.0, 34.0), + Cesium.Cartographic.fromDegrees(-101.0, 36.0), + Cesium.Cartographic.fromDegrees(-103.0, 36.0) + ]) + }] }] }] - }] - }; + }, + pickData : 'polygon3' + }); + + primitive = new Cesium.Primitive({ + geometries : [ polygon ], + appearance : createAppearance(new Cesium.Color(0.0, 1.0, 1.0, 0.75)) + }); + primitives.add(primitive); - polygonHierarchy.material = Cesium.Material.fromType(scene.getContext(), 'Color'); - polygonHierarchy.material.uniforms.color = new Cesium.Color(0.0, 1.0, 1.0, 0.75); - polygonHierarchy.configureFromPolygonHierarchy(hierarchy); - primitives.add(polygonHierarchy); // Create a polygon from an extent - var polygonExtent = new Cesium.Polygon(); - Sandcastle.declare(polygonExtent); // For highlighting on mouseover in Sandcastle. - polygonExtent.configureExtent( - new Cesium.Extent( - Cesium.Math.toRadians(-180.0), - Cesium.Math.toRadians(50.0), - Cesium.Math.toRadians(180.0), - Cesium.Math.toRadians(90.0))); - primitives.add(polygonExtent); + polygon = new Cesium.PolygonGeometry({ + extent : new Cesium.Extent(Cesium.Math.toRadians(-180.0), + Cesium.Math.toRadians(50.0), + Cesium.Math.toRadians(180.0), + Cesium.Math.toRadians(90.0)), + pickData : 'polygon4' + }); + + primitive = new Cesium.Primitive({ + geometries : [ polygon ], + appearance : createAppearance({red: 1.0, green: 1.0, blue: 0.0, alpha: 0.75}) + }); + primitives.add(primitive); + // Apply a material to a polygon - var checkeredPolygon = new Cesium.Polygon(); - Sandcastle.declare(checkeredPolygon); // For highlighting on mouseover in Sandcastle. - checkeredPolygon.setPositions(ellipsoid.cartographicArrayToCartesianArray([ - Cesium.Cartographic.fromDegrees(-90.0, 30.0), - Cesium.Cartographic.fromDegrees(-80.0, 30.0), - Cesium.Cartographic.fromDegrees(-80.0, 40.0), - Cesium.Cartographic.fromDegrees(-90.0, 40.0) - ])); - checkeredPolygon.material = Cesium.Material.fromType(scene.getContext(), 'Checkerboard'); - primitives.add(checkeredPolygon); + polygon = new Cesium.PolygonGeometry({ + positions : ellipsoid.cartographicArrayToCartesianArray([ + Cesium.Cartographic.fromDegrees(-90.0, 30.0), + Cesium.Cartographic.fromDegrees(-80.0, 30.0), + Cesium.Cartographic.fromDegrees(-80.0, 40.0), + Cesium.Cartographic.fromDegrees(-90.0, 40.0) + ]), + pickData : 'polygon5' + }); + + var appearance = new Cesium.Appearance({ + material : Cesium.Material.fromType(scene.getContext(), 'Checkerboard') + }); + + primitive = new Cesium.Primitive({ + geometries : [ polygon ], + appearance : appearance + }); + primitives.add(primitive); } var widget = new CesiumViewerWidget({ @@ -150,4 +197,4 @@ }); - \ No newline at end of file + diff --git a/CHANGES.md b/CHANGES.md index 99856943fcaf..0ad11cb9b1dd 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -22,6 +22,7 @@ Beta Releases * Added renderer support for `OES_element_index_uint`, which can improve performance by reducing batch sizes. * Added `czm_tangentToEyeSpaceMatrix` built-in GLSL function. * Added WallGeometry +* Added PolygonGeometry ### b17 - 2013-06-03 diff --git a/Source/Core/PolygonGeometry.js b/Source/Core/PolygonGeometry.js new file mode 100644 index 000000000000..c20f6b2cdc21 --- /dev/null +++ b/Source/Core/PolygonGeometry.js @@ -0,0 +1,317 @@ +/*global define*/ +define([ + './DeveloperError', + './Cartesian2', + './Cartesian3', + './Cartesian4', + './Matrix3', + './Cartographic', + './Ellipsoid', + './Math', + './Matrix4', + './ComponentDatatype', + './PrimitiveType', + './defaultValue', + './BoundingSphere', + './GeometryAttribute', + './GeometryIndices', + './PolygonPipeline', + './EllipsoidTangentPlane', + './WindingOrder', + './BoundingRectangle', + './Quaternion', + './GeometryFilters', + './ExtentTessellator', + './Queue', + './Intersect', + '../Scene/sampleTerrain', + '../ThirdParty/when' + ], function( + DeveloperError, + Cartesian2, + Cartesian3, + Cartesian4, + Matrix3, + Cartographic, + Ellipsoid, + CesiumMath, + Matrix4, + ComponentDatatype, + PrimitiveType, + defaultValue, + BoundingSphere, + GeometryAttribute, + GeometryIndices, + PolygonPipeline, + EllipsoidTangentPlane, + WindingOrder, + BoundingRectangle, + Quaternion, + GeometryFilters, + ExtentTessellator, + Queue, + Intersect, + sampleTerrain, + when) { + "use strict"; + + /** + * Creates a PolygonGeometry. The polygon itself is either defined by an array of Cartesian points, + * an extent or a polygon hierarchy. + * + * @alias PolygonGeometry + * @constructor + * + * @param {array of Cartesian} [positions] an array of positions that defined the corner points of the polygon + * @param {Extent} [extent] an extent that defines a polygon. if a rotation attribute is supplied, the extent + * is also rotated + * @param {polygon hierarchy} [polygonHierarchy] a polygon hierarchy that can include holes + * @param {number} [height=0,0] the height of the polygon, + * @param {radians} [rotation=0.0] if supplied with an extent, the extent is rotated by this angle + * @param {object} [pickData] the geometry pick data + * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] the ellipsoid to be used as a reference + * + * @exception {DeveloperError} All dimensions components must be greater than or equal to zero. + * + * @example + * + * // create a polygon from points + * var polygon = new Cesium.PolygonGeometry({ + * positions : ellipsoid.cartographicArrayToCartesianArray([ + * Cesium.Cartographic.fromDegrees(-72.0, 40.0), + * Cesium.Cartographic.fromDegrees(-70.0, 35.0), + * Cesium.Cartographic.fromDegrees(-75.0, 30.0), + * Cesium.Cartographic.fromDegrees(-70.0, 30.0), + * Cesium.Cartographic.fromDegrees(-68.0, 40.0) + * ]), + * pickData : 'polygon1' + * }); + * + * // create a polygon from an extent with rotation + * polygon = new Cesium.PolygonGeometry({ + * extent : new Cesium.Extent(Cesium.Math.toRadians(-110.0), + * Cesium.Math.toRadians(0.0), + * Cesium.Math.toRadians(-90.0), + * Cesium.Math.toRadians(20.0)), + * height : 0.0, + * rotation : Cesium.Math.toRadians(45), + * pickData : 'polygon2' + * }); + * + * // create a nested polygon with holes + * polygon = new Cesium.PolygonGeometry({ + * polygonHierarchy : { + * positions : ellipsoid.cartographicArrayToCartesianArray( + * [ + * Cesium.Cartographic.fromDegrees(-109.0, 30.0), + * Cesium.Cartographic.fromDegrees(-95.0, 30.0), + * Cesium.Cartographic.fromDegrees(-95.0, 40.0), + * Cesium.Cartographic.fromDegrees(-109.0, 40.0) + * ]), + * holes : [{ + * positions : ellipsoid.cartographicArrayToCartesianArray( + * [ + * Cesium.Cartographic.fromDegrees(-107.0, 31.0), + * Cesium.Cartographic.fromDegrees(-107.0, 39.0), + * Cesium.Cartographic.fromDegrees(-97.0, 39.0), + * Cesium.Cartographic.fromDegrees(-97.0, 31.0) + * ]), + * holes : [{ + * positions : ellipsoid.cartographicArrayToCartesianArray( + * [ + * Cesium.Cartographic.fromDegrees(-105.0, 33.0), + * Cesium.Cartographic.fromDegrees(-99.0, 33.0), + * Cesium.Cartographic.fromDegrees(-99.0, 37.0), + * Cesium.Cartographic.fromDegrees(-105.0, 37.0) + * ]), + * holes : [{ + * positions : ellipsoid.cartographicArrayToCartesianArray( + * [ + * Cesium.Cartographic.fromDegrees(-103.0, 34.0), + * Cesium.Cartographic.fromDegrees(-101.0, 34.0), + * Cesium.Cartographic.fromDegrees(-101.0, 36.0), + * Cesium.Cartographic.fromDegrees(-103.0, 36.0) + * ]) + * }] + * }] + * }] + * }, + * pickData : 'polygon3' + * }); + */ + var PolygonGeometry = function(options) { + options = defaultValue(options, defaultValue.EMPTY_OBJECT); + + var ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84); + var meshes = []; + var mesh; + var boundingVolume; + var i; + + if (typeof options.positions !== 'undefined') { + // create from positions + this.positions = options.positions; + + boundingVolume = BoundingSphere.fromPoints(this.positions); + mesh = this.createMeshFromPositions(this.positions, boundingVolume); + if (typeof mesh !== 'undefined') { + meshes.push(mesh); + } + + } else if (typeof options.extent !== 'undefined') { + // create from an extent + this.extent = options.extent; + this.rotation = options.rotation; + + boundingVolume = BoundingSphere.fromExtent3D(this.extent, ellipsoid); + + mesh = ExtentTessellator.compute({ + extent : this.extent, + rotation : this.rotation, + generateTextureCoordinates : true + }); + if (typeof mesh !== 'undefined') { + meshes.push(mesh); + } + + } else if (typeof options.polygonHierarchy !== 'undefined') { + // create from a polygon hierarchy + this.polygonHierarchy = options.polygonHierarchy; + + // Algorithm adapted from http://www.geometrictools.com/Documentation/TriangulationByEarClipping.pdf + var polygons = []; + var queue = new Queue(); + queue.enqueue(this.polygonHierarchy); + + while (queue.length !== 0) { + var outerNode = queue.dequeue(); + var outerRing = outerNode.positions; + + if (outerRing.length < 3) { + throw new DeveloperError('At least three positions are required.'); + } + + var numChildren = outerNode.holes ? outerNode.holes.length : 0; + if (numChildren === 0) { + // The outer polygon is a simple polygon with no nested inner polygon. + polygons.push(outerNode.positions); + } else { + // The outer polygon contains inner polygons + var holes = []; + for (i = 0; i < numChildren; i++) { + var hole = outerNode.holes[i]; + holes.push(hole.positions); + + var numGrandchildren = 0; + if (hole.holes) { + numGrandchildren = hole.holes.length; + } + + for ( var j = 0; j < numGrandchildren; j++) { + queue.enqueue(hole.holes[j]); + } + } + var combinedPolygon = PolygonPipeline.eliminateHoles(outerRing, holes); + polygons.push(combinedPolygon); + } + } + + this.polygonHierarchy = polygons; + + var outerPositions = this.polygonHierarchy[0]; + // The bounding volume is just around the boundary points, so there could be cases for + // contrived polygons on contrived ellipsoids - very oblate ones - where the bounding + // volume doesn't cover the polygon. + boundingVolume = BoundingSphere.fromPoints(outerPositions); + + for (i = 0; i < this.polygonHierarchy.length; i++) { + mesh = this.createMeshFromPositions(this.polygonHierarchy[i], boundingVolume); + if (typeof mesh !== 'undefined') { + meshes.push(mesh); + } + } + + } else { + throw new DeveloperError('positions, extent or hierarchy must be supplied.'); + } + + var attributes = {}; + var indexLists = []; + + mesh = GeometryFilters.combine(meshes); + mesh = PolygonPipeline.scaleToGeodeticHeight(mesh, defaultValue(options.height, 0.0), ellipsoid); + mesh = GeometryFilters.reorderForPostVertexCache(mesh); + mesh = GeometryFilters.reorderForPreVertexCache(mesh); + + attributes.position = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : mesh.attributes.position.values + }); + + indexLists.push( + new GeometryIndices({ + primitiveType : PrimitiveType.TRIANGLES, + values : mesh.indexLists[0].values + })); + + /** + * The height of the polygon. + */ + this.height = defaultValue(options.height, 0.0); + + /** + * The attributes (vertices) + */ + this.attributes = attributes; + + /** + * The indexes used for GL rendering + */ + this.indexLists = indexLists; + + /** + * The bounding sphere for the whole geometry + */ + this.boundingSphere = boundingVolume; + + /** + * The model matrix, simply the identity + */ + this.modelMatrix = defaultValue(options.modelMatrix, Matrix4.IDENTITY.clone()); + + /** + * Pick data used for selection + */ + this.pickData = options.pickData; + }; + + PolygonGeometry.prototype.createMeshFromPositions = function(positions, boundingSphere, outerPositions) { + var cleanedPositions = PolygonPipeline.cleanUp(positions); + if (cleanedPositions.length < 3) { + // Duplicate positions result in not enough positions to form a polygon. + return undefined; + } + + var tangentPlane = EllipsoidTangentPlane.fromPoints(cleanedPositions, this.ellipsoid); + var positions2D = tangentPlane.projectPointsOntoPlane(cleanedPositions); + + var originalWindingOrder = PolygonPipeline.computeWindingOrder2D(positions2D); + if (originalWindingOrder === WindingOrder.CLOCKWISE) { + positions2D.reverse(); + cleanedPositions.reverse(); + } + var indices = PolygonPipeline.earClip2D(positions2D); + // Checking bounding sphere with plane for quick reject + var minX = boundingSphere.center.x - boundingSphere.radius; + if ((minX < 0) && (BoundingSphere.intersect(boundingSphere, Cartesian4.UNIT_Y) === Intersect.INTERSECTING)) { + indices = PolygonPipeline.wrapLongitude(cleanedPositions, indices); + } + var mesh = PolygonPipeline.computeSubdivision(cleanedPositions, indices, this._granularity); + + return mesh; + }; + + return PolygonGeometry; +}); + diff --git a/Specs/Core/PolygonGeometrySpec.js b/Specs/Core/PolygonGeometrySpec.js new file mode 100644 index 000000000000..93efcf1940fd --- /dev/null +++ b/Specs/Core/PolygonGeometrySpec.js @@ -0,0 +1,284 @@ +/*global defineSuite*/ +defineSuite([ + 'Core/PolygonGeometry', + 'Specs/createContext', + 'Specs/destroyContext', + 'Specs/createCamera', + 'Specs/createFrameState', + 'Specs/frameState', + 'Specs/pick', + 'Specs/render', + 'Core/BoundingRectangle', + 'Core/BoundingSphere', + 'Core/Cartesian3', + 'Core/Cartographic', + 'Core/Ellipsoid', + 'Core/Extent', + 'Core/Matrix4', + 'Core/Math', + 'Core/JulianDate', + 'Renderer/BufferUsage', + 'Renderer/ClearCommand', + 'Scene/Material', + 'Scene/Appearance', + 'Scene/Primitive', + 'Scene/SceneMode' + ], function( + PolygonGeometry, + createContext, + destroyContext, + createCamera, + createFrameState, + frameState, + pick, + render, + BoundingRectangle, + BoundingSphere, + Cartesian3, + Cartographic, + Ellipsoid, + Extent, + Matrix4, + CesiumMath, + JulianDate, + BufferUsage, + ClearCommand, + Material, + Appearance, + Primitive, + SceneMode) { + "use strict"; + /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/ + + var context; + var polygon; + var us; + + beforeAll(function() { + context = createContext(); + }); + + afterAll(function() { + destroyContext(context); + }); + + beforeEach(function() { + polygon = createPolygonGeometry(); + + us = context.getUniformState(); + us.update(createFrameState(createCamera(context, new Cartesian3(1.02, 0.0, 0.0), Cartesian3.ZERO, Cartesian3.UNIT_Z))); + }); + + afterEach(function() { + polygon = undefined; + us = undefined; + }); + + function createPolygonGeometry() { + var ellipsoid = Ellipsoid.UNIT_SPHERE; + + var p = new PolygonGeometry({ + positions : [ + ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-50.0, -50.0, 0.0)), + ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(50.0, -50.0, 0.0)), + ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(50.0, 50.0, 0.0)), + ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-50.0, 50.0, 0.0)) + ], + ellipsoid : ellipsoid + }); + + return p; + } + + it('create throws with less than three positions', function() { + expect(function() { + var p = new PolygonGeometry({ positions : [new Cartesian3()] }); + }).toThrow(); + }); + + it('create polygon from hierarchy', function() { + var hierarchy = { + positions : Ellipsoid.WGS84.cartographicArrayToCartesianArray([ + new Cartographic.fromDegrees(-124.0, 35.0, 0.0), + new Cartographic.fromDegrees(-110.0, 35.0, 0.0), + new Cartographic.fromDegrees(-110.0, 40.0, 0.0), + new Cartographic.fromDegrees(-124.0, 40.0, 0.0) + ]), + holes : [{ + positions : Ellipsoid.WGS84.cartographicArrayToCartesianArray([ + new Cartographic.fromDegrees(-122.0, 36.0, 0.0), + new Cartographic.fromDegrees(-122.0, 39.0, 0.0), + new Cartographic.fromDegrees(-112.0, 39.0, 0.0), + new Cartographic.fromDegrees(-112.0, 36.0, 0.0) + ]), + holes : [{ + positions : Ellipsoid.WGS84.cartographicArrayToCartesianArray([ + new Cartographic.fromDegrees(-120.0, 36.5, 0.0), + new Cartographic.fromDegrees(-114.0, 36.5, 0.0), + new Cartographic.fromDegrees(-114.0, 38.5, 0.0), + new Cartographic.fromDegrees(-120.0, 38.5, 0.0) + ]) + }] + }] + }; + + var p = new PolygonGeometry({ polygonHierarchy : hierarchy }); + }); + + it('create polygon from clockwise hierarchy', function() { + var hierarchy = { + positions : Ellipsoid.WGS84.cartographicArrayToCartesianArray([ + new Cartographic.fromDegrees(-124.0, 35.0, 0.0), + new Cartographic.fromDegrees(-124.0, 40.0, 0.0), + new Cartographic.fromDegrees(-110.0, 40.0, 0.0), + new Cartographic.fromDegrees(-110.0, 35.0, 0.0) + ]), + holes : [{ + positions : Ellipsoid.WGS84.cartographicArrayToCartesianArray([ + new Cartographic.fromDegrees(-122.0, 36.0, 0.0), + new Cartographic.fromDegrees(-112.0, 36.0, 0.0), + new Cartographic.fromDegrees(-112.0, 39.0, 0.0), + new Cartographic.fromDegrees(-122.0, 39.0, 0.0) + ]), + holes : [{ + positions : Ellipsoid.WGS84.cartographicArrayToCartesianArray([ + new Cartographic.fromDegrees(-120.0, 36.5, 0.0), + new Cartographic.fromDegrees(-120.0, 38.5, 0.0), + new Cartographic.fromDegrees(-114.0, 38.5, 0.0), + new Cartographic.fromDegrees(-114.0, 36.5, 0.0) + ]) + }] + }] + }; + + var p = new PolygonGeometry({ polygonHierarchy : hierarchy }); + }); + + it('create from PolygonHierarchy throws with less than three positions', function() { + var hierarchy = { + positions : Ellipsoid.WGS84.cartographicArrayToCartesianArray([ + new Cartographic() + ]) + }; + expect(function() { + var p = new PolygonGeometry({ polygonHierarchy : hierarchy }); + }).toThrow(); + }); + + it('create from extent', function() { + var extent = new Extent( + 0.0, + 0.0, + CesiumMath.toRadians(10.0), + CesiumMath.toRadians(10.0) + ); + + var p = new PolygonGeometry({ extent : extent }); + }); + + it('renders', function() { + // This test fails in Chrome if a breakpoint is set inside this function. Strange. + + var material = Material.fromType(undefined, Material.ColorType); + material.uniforms.color = { red : 1.0, green : 0.0, blue : 0.0, alpha : 1.0 }; + var appearance = new Appearance({ material : material }); + + var primitive = new Primitive({ geometries : [ polygon ], appearance : appearance }); + + ClearCommand.ALL.execute(context); + expect(context.readPixels()).toEqual([0, 0, 0, 0]); + + render(context, frameState, primitive); + expect(context.readPixels()).not.toEqual([0, 0, 0, 0]); + }); + + it('renders extent', function() { + // This test fails in Chrome if a breakpoint is set inside this function. Strange. + + var ellipsoid = Ellipsoid.UNIT_SPHERE; + var p = new PolygonGeometry({ + extent : new Extent( + 0.0, + 0.0, + CesiumMath.toRadians(10.0), + CesiumMath.toRadians(10.0) + ), + ellipsoid : ellipsoid + }); + + var material = Material.fromType(undefined, Material.ColorType); + material.uniforms.color = { red : 1.0, green : 0.0, blue : 0.0, alpha : 1.0 }; + var appearance = new Appearance({ material : material }); + + var primitive = new Primitive({ geometries : [ p ], appearance : appearance }); + + ClearCommand.ALL.execute(context); + expect(context.readPixels()).toEqual([0, 0, 0, 0]); + + render(context, frameState, primitive); + expect(context.readPixels()).not.toEqual([0, 0, 0, 0]); + }); + + it('does not render when show is false', function() { + var material = Material.fromType(undefined, Material.ColorType); + material.uniforms.color = { red : 1.0, green : 0.0, blue : 0.0, alpha : 1.0 }; + var appearance = new Appearance({ material : material }); + var primitive = new Primitive({ geometries : [ polygon ], appearance : appearance }); + primitive.show = false; + + expect(render(context, frameState, primitive)).toEqual(0); + }); + + it('cannot create due to duplicate positions', function() { + var ellipsoid = Ellipsoid.UNIT_SPHERE; + + expect(function() { + polygon = new PolygonGeometry({ + positions : [ + ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(0.0, 0.0, 0.0)), + ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(0.0, 0.0, 0.0)), + ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(0.0, 0.0, 0.0)) + ], + ellipsoid : ellipsoid + }); + }).toThrow(); + }); + + it('cannot create due to duplicate hierarchy positions', function() { + var ellipsoid = Ellipsoid.UNIT_SPHERE; + var hierarchy = { + positions : ellipsoid.cartographicArrayToCartesianArray([ + new Cartographic.fromDegrees(1.0, 1.0, 0.0), + new Cartographic.fromDegrees(1.0, 1.0, 0.0), + new Cartographic.fromDegrees(1.0, 1.0, 0.0) + ]), + holes : [{ + positions : ellipsoid.cartographicArrayToCartesianArray([ + new Cartographic.fromDegrees(0.0, 0.0, 0.0), + new Cartographic.fromDegrees(0.0, 0.0, 0.0), + new Cartographic.fromDegrees(0.0, 0.0, 0.0) + ]) + }] + }; + + expect(function() { + polygon = new PolygonGeometry({ polygonHierarchy : hierarchy, ellipsoid : ellipsoid }); + }).toThrow(); + }); + + it('cannot create with empty extent', function() { + var ellipsoid = Ellipsoid.UNIT_SPHERE; + var extent = new Extent( + 0.0, + 0.0, + 0.0, + 0.0 + ); + + expect(function() { + polygon = new PolygonGeometry({ extent : extent, ellipsoid : ellipsoid }); + }).toThrow(); + }); + + +}, 'WebGL'); From 2d57ec1f6192d6c0e6c21c119e4392ea24506044 Mon Sep 17 00:00:00 2001 From: Akos Maroy Date: Wed, 22 May 2013 14:18:53 +0200 Subject: [PATCH 058/306] updated WallGeometry to expect positions in Cartesian instead of Cartographic --- Apps/Sandcastle/gallery/Wall.html | 6 ++--- Source/Core/WallGeometry.js | 42 ++++++++++++++++--------------- Specs/Core/WallGeometrySpec.js | 14 +++++++---- 3 files changed, 34 insertions(+), 28 deletions(-) diff --git a/Apps/Sandcastle/gallery/Wall.html b/Apps/Sandcastle/gallery/Wall.html index f068f7b81c95..cb1381b549d0 100644 --- a/Apps/Sandcastle/gallery/Wall.html +++ b/Apps/Sandcastle/gallery/Wall.html @@ -94,7 +94,7 @@ // create a wall that spans from ground level to 10000 meters var wall1 = new Cesium.WallGeometry({ altitudeMode : 'absolute', - coordinates : coords, + positions : ellipsoid.cartographicArrayToCartesianArray(coords), pickData : 'wall1' }); @@ -109,7 +109,7 @@ // create a wall with the same coordinates, but from 15000 - 25000 meters var wall2 = new Cesium.WallGeometry({ altitudeMode : 'absolute', - coordinates : coords, + positions : ellipsoid.cartographicArrayToCartesianArray(coords), bottom : 15000, top : 25000, pickData : 'wall2' @@ -143,7 +143,7 @@ var wall3 = new Cesium.WallGeometry({ altitudeMode : 'relativeToGround', - coordinates : coords, + positions : ellipsoid.cartographicArrayToCartesianArray(coords), terrain : terrain, pickData : 'wall3' }); diff --git a/Source/Core/WallGeometry.js b/Source/Core/WallGeometry.js index 79ed43f48d85..2c1e03871cdb 100644 --- a/Source/Core/WallGeometry.js +++ b/Source/Core/WallGeometry.js @@ -39,29 +39,30 @@ define([ * @alias WallGeometry * @constructor * - * @param {array of Cartographic} coordinates an array of Cartographic objects, which are the coordinates of the wall + * @param {array of Cartesian} positions an array of Cartesian objects, which are the points of the wall * @param {string} altitudeMode either 'absolute' or 'relativeToGround'. 'absolute' means the height * is treated from the WGS84 ellipsoid. 'relativeToGround' means they are treated * relative to the supplied terrain data - * @param {array of Cartographic} [terrain] requred if altitudeMode is 'relativeToGround'. has to denote the same points - * as in coordinates, with the ground elevation in the height property of each point + * @param {array of Cartesian} [terrain] requred if altitudeMode is 'relativeToGround'. has to denote the same points + * as in positions, with the ground elevation reflecting the terrain elevation * @param {number} [top] optional, the top of the wall. if specified, the top of the wall is treated as this - * height, and the information in the coordinates array is disregarded + * height, and the information in the positions array is disregarded * @param {number} [bottom] optional, the bottom of the wall. if specified, the bottom of the wall is treated as * this height. otherwise its treated as 'ground' (the WGS84 ellipsoid height 0) * @param {object} [pickData] the geometry pick data + * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] ellispoid for coordinate manipulation * * @exception {DeveloperError} All dimensions components must be greater than or equal to zero. */ var WallGeometry = function(options) { options = defaultValue(options, defaultValue.EMPTY_OBJECT); - var coordinates; + var positions; - if (typeof options.coordinates !== 'undefined') { - coordinates = options.coordinates; + if (typeof options.positions !== 'undefined') { + positions = options.positions; } else { - throw new DeveloperError('Coordinates must be supplied.'); + throw new DeveloperError('positions must be supplied.'); } var attributes = {}; @@ -70,12 +71,11 @@ define([ if (options.altitudeMode === 'relativeToGround' && typeof options.terrain === 'undefined') { throw new DeveloperError('No terrain supplied when required.'); } - if (typeof options.terrain !== 'undefined' && options.terrain.length !== options.coordinates.length) { + if (typeof options.terrain !== 'undefined' && options.terrain.length !== options.positions.length) { throw new DeveloperError('Coordinates and terrain points don\'t match in number'); } - var c = new Cartographic(); - var ellipsoid = Ellipsoid.WGS84; + var ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84); attributes.position = new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, @@ -85,8 +85,11 @@ define([ // add lower and upper points one after the other, lower // points being even and upper points being odd - for (var i = 0; i < options.coordinates.length; ++i) { - c = Cartographic.clone(options.coordinates[i]); + var origHeight; + var c; + for (var i = 0; i < options.positions.length; ++i) { + c = ellipsoid.cartesianToCartographic(options.positions[i]); + origHeight = c.height; c.height = 0; if (options.bottom !== undefined) { c.height = options.bottom; @@ -104,8 +107,7 @@ define([ attributes.position.values.push(v.z); // get the original height back, or set the top value - c.height = options.top === undefined ? options.coordinates[i].height - : options.top; + c.height = options.top === undefined ? origHeight : options.top; if (options.terrain !== undefined && !isNaN(options.terrain[i].height)) { c.height += options.terrain[i].height; } @@ -254,21 +256,21 @@ define([ altitudeMode = xpResult.stringValue; var options = { - altitudeMode : altitudeMode, - coordinates : coordinates + altitudeMode : altitudeMode, + positions : Ellipsoid.WGS84.cartographicArrayToCartesianArray(coordinates) }; if (altitudeMode === 'relativeToGround') { // request the terrain data for each point of the line string var coords = []; - for (i = 0; i < options.coordinates.length; ++i) { - coords.push(Cartographic.clone(options.coordinates[i])); + for (i = 0; i < options.positions.length; ++i) { + coords.push(Ellipsoid.WGS84.cartesianToCartographic(options.positions[i])); } // request the elevation ground data when(sampleTerrain(terrainProvider, 11, coords), function(positions) { - options.terrain = positions; + options.terrain = Ellipsoid.WGS84.cartographicArrayToCartesianArray(positions); var wall = new WallGeometry(options); callback(wall); diff --git a/Specs/Core/WallGeometrySpec.js b/Specs/Core/WallGeometrySpec.js index 7f84a8a072d5..bf3041fe1fc7 100644 --- a/Specs/Core/WallGeometrySpec.js +++ b/Specs/Core/WallGeometrySpec.js @@ -1,13 +1,17 @@ /*global defineSuite*/ defineSuite([ 'Core/WallGeometry', - 'Core/Cartographic' + 'Core/Cartographic', + 'Core/Ellipsoid' ], function( WallGeometry, - Cartographic) { + Cartographic, + Ellipsoid) { "use strict"; /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/ + var ellipsoid = Ellipsoid.WGS84; + it('create with no parameters', function() { expect(function() { return new WallGeometry({ @@ -23,7 +27,7 @@ defineSuite([ var w = new WallGeometry({ altitudeMode : 'absolute', - coordinates : coords + positions : ellipsoid.cartographicArrayToCartesianArray(coords) }); expect(w.attributes.position.values.length).toEqual(2 * 2 * 3); @@ -40,7 +44,7 @@ defineSuite([ expect(function() { return new WallGeometry({ altitudeMode : 'relativeToGround', - coordinates : coords + positions : ellipsoid.cartographicArrayToCartesianArray(coords) }).toThrow(); }); }); @@ -58,7 +62,7 @@ defineSuite([ var w = new WallGeometry({ altitudeMode : 'relativeToGround', - coordinates : coords, + positions : ellipsoid.cartographicArrayToCartesianArray(coords), terrain : terrain }); From 1c61bfce929be8671a3c8b9eccf179aa633032fc Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Wed, 22 May 2013 13:57:19 -0400 Subject: [PATCH 059/306] Rename ExtentTessellator to ExtentGeometry. --- Apps/CesiumViewer/CesiumViewer.js | 6 ++-- ...ExtentTessellator.js => ExtentGeometry.js} | 24 +++++++-------- Source/Scene/Polygon.js | 10 +++---- ...ssellatorSpec.js => ExtentGeometrySpec.js} | 30 +++++++++---------- 4 files changed, 35 insertions(+), 35 deletions(-) rename Source/Core/{ExtentTessellator.js => ExtentGeometry.js} (96%) rename Specs/Core/{ExtentTessellatorSpec.js => ExtentGeometrySpec.js} (92%) diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index f81fb7c19f54..73767f8cc5aa 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -11,7 +11,7 @@ define([ 'Core/Matrix4', 'Core/Ellipsoid', 'Core/Extent', - 'Core/ExtentTessellator', + 'Core/ExtentGeometry', 'Core/EllipsoidGeometry', 'Core/BoxGeometry', 'Core/GeometryFilters', @@ -36,7 +36,7 @@ define([ Matrix4, Ellipsoid, Extent, - ExtentTessellator, + ExtentGeometry, EllipsoidGeometry, BoxGeometry, GeometryFilters, @@ -72,7 +72,7 @@ define([ var scene = widget.scene; - var mesh = ExtentTessellator.compute({ + var mesh = ExtentGeometry.compute({ extent : new Extent( CesiumMath.toRadians(-180.0), CesiumMath.toRadians(50.0), diff --git a/Source/Core/ExtentTessellator.js b/Source/Core/ExtentGeometry.js similarity index 96% rename from Source/Core/ExtentTessellator.js rename to Source/Core/ExtentGeometry.js index df7410f71c22..002a58162a60 100644 --- a/Source/Core/ExtentTessellator.js +++ b/Source/Core/ExtentGeometry.js @@ -36,9 +36,9 @@ define([ /** * Contains class functions to create a mesh or vertex array from a cartographic extent. * - * @exports ExtentTessellator + * @exports ExtentGeometry */ - var ExtentTessellator = {}; + var ExtentGeometry = {}; function isValidLatLon(latitude, longitude) { if (latitude < -CesiumMath.PI_OVER_TWO || latitude > CesiumMath.PI_OVER_TWO) { @@ -51,7 +51,7 @@ define([ } /** * Compute vertices from a cartographic extent. This function is different from - * {@link ExtentTessellator#compute} and {@link ExtentTessellator#computeBuffers} + * {@link ExtentGeometry#compute} and {@link ExtentGeometry#computeBuffers} * in that it assumes that you have already allocated output arrays of the correct size. * * @param {Extent} description.extent A cartographic extent with north, south, east and west properties in radians. @@ -73,7 +73,7 @@ define([ var center = new Cartesian3(); var rotationMatrix = new Matrix2(); var proj = new GeographicProjection(); - ExtentTessellator.computeVertices = function(description) { + ExtentGeometry.computeVertices = function(description) { description = defaultValue(description, defaultValue.EMPTY_OBJECT); var extent = description.extent; extent.validate(); @@ -238,7 +238,7 @@ define([ * * @example * // Create a vertex array for rendering a wireframe extent. - * var mesh = ExtentTessellator.compute({ + * var mesh = ExtentGeometry.compute({ * ellipsoid : Ellipsoid.WGS84, * extent : new Extent( * CesiumMath.toRadians(-80.0), @@ -255,7 +255,7 @@ define([ * attributeIndices : GeometryFilters.createAttributeIndices(mesh) * }); */ - ExtentTessellator.compute = function(description) { + ExtentGeometry.compute = function(description) { description = defaultValue(description, defaultValue.EMPTY_OBJECT); // make a copy of description to allow us to change values before passing to computeVertices @@ -284,7 +284,7 @@ define([ computeVerticesDescription.textureCoordinates = textureCoordinates; computeVerticesDescription.indices = indices; - ExtentTessellator.computeVertices(computeVerticesDescription); + ExtentGeometry.computeVertices(computeVerticesDescription); if (indices.length === 0) { return undefined; @@ -341,7 +341,7 @@ define([ * @example * // Example 1: * // Create a vertex array for a solid extent, with separate positions and texture coordinates. - * var buffers = ExtentTessellator.computeBuffers({ + * var buffers = ExtentGeometry.computeBuffers({ * ellipsoid : ellipsoid, * extent : extent, * generateTextureCoordinates : true @@ -368,7 +368,7 @@ define([ * @example * // Example 2: * // Create a vertex array for a solid extent, with interleaved positions and texture coordinates. - * var buffers = ExtentTessellator.computeBuffers({ + * var buffers = ExtentGeometry.computeBuffers({ * ellipsoid : ellipsoid, * extent : extent, * generateTextureCoordinates : true, @@ -400,7 +400,7 @@ define([ * var indexBuffer = context.createIndexBuffer(new Uint16Array(buffers.indices), usage, IndexDatatype.UNSIGNED_SHORT); * var vacontext.createVertexArray(attributes, indexBuffer); */ - ExtentTessellator.computeBuffers = function(description) { + ExtentGeometry.computeBuffers = function(description) { description = defaultValue(description, defaultValue.EMPTY_OBJECT); // make a copy of description to allow us to change values before passing to computeVertices @@ -429,7 +429,7 @@ define([ computeVerticesDescription.textureCoordinates = textureCoordinates; computeVerticesDescription.indices = indices; - ExtentTessellator.computeVertices(computeVerticesDescription); + ExtentGeometry.computeVertices(computeVerticesDescription); var result = { indices : indices @@ -447,5 +447,5 @@ define([ return result; }; - return ExtentTessellator; + return ExtentGeometry; }); diff --git a/Source/Scene/Polygon.js b/Source/Scene/Polygon.js index 7bdca1966aa4..1e0ccb1fff88 100644 --- a/Source/Scene/Polygon.js +++ b/Source/Scene/Polygon.js @@ -19,7 +19,7 @@ define([ '../Core/EllipsoidTangentPlane', '../Core/PolygonPipeline', '../Core/WindingOrder', - '../Core/ExtentTessellator', + '../Core/ExtentGeometry', '../Core/Intersect', '../Core/Queue', '../Core/Matrix3', @@ -55,7 +55,7 @@ define([ EllipsoidTangentPlane, PolygonPipeline, WindingOrder, - ExtentTessellator, + ExtentGeometry, Intersect, Queue, Matrix3, @@ -565,9 +565,9 @@ define([ var mesh; if ((typeof polygon._extent !== 'undefined') && !polygon._extent.isEmpty()) { - mesh = ExtentTessellator.compute({ - extent : polygon._extent, - rotation : polygon.rotation, + mesh = ExtentGeometry.compute({ + extent : polygon._extent, + rotation : polygon.rotation, generateTextureCoordinates : true }); if (typeof mesh !== 'undefined') { diff --git a/Specs/Core/ExtentTessellatorSpec.js b/Specs/Core/ExtentGeometrySpec.js similarity index 92% rename from Specs/Core/ExtentTessellatorSpec.js rename to Specs/Core/ExtentGeometrySpec.js index 1fe1d40e2c49..15032e5d386e 100644 --- a/Specs/Core/ExtentTessellatorSpec.js +++ b/Specs/Core/ExtentGeometrySpec.js @@ -1,12 +1,12 @@ /*global defineSuite*/ defineSuite([ - 'Core/ExtentTessellator', + 'Core/ExtentGeometry', 'Core/Extent', 'Core/Ellipsoid', 'Core/Cartesian3', 'Core/Math' ], function( - ExtentTessellator, + ExtentGeometry, Extent, Ellipsoid, Cartesian3, @@ -15,7 +15,7 @@ defineSuite([ /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/ it('compute 0', function() { - var m = ExtentTessellator.compute({ + var m = ExtentGeometry.compute({ extent : new Extent(-2.0, -1.0, 0.0, 1.0), granularity : 1.0 }); @@ -25,7 +25,7 @@ defineSuite([ }); it('compute 1', function() { - var m = ExtentTessellator.compute({ + var m = ExtentGeometry.compute({ extent : new Extent(-2.0, -1.0, 0.0, 1.0), granularity : 1.0, generateTextureCoordinates : true @@ -36,7 +36,7 @@ defineSuite([ }); it('compute returns undefined if rotation makes extent invalid', function() { - expect(typeof ExtentTessellator.compute({ + expect(typeof ExtentGeometry.compute({ extent : new Extent(-CesiumMath.PI, -1.0, 0.0, 1.0), rotation: CesiumMath.PI_OVER_TWO, granularity : 1.0, @@ -45,7 +45,7 @@ defineSuite([ }); it('computeBuffers 0', function() { - var buffers = ExtentTessellator.computeBuffers({ + var buffers = ExtentGeometry.computeBuffers({ extent : new Extent(-2.0, -1.0, 0.0, 1.0), granularity : 1.0 }); @@ -55,7 +55,7 @@ defineSuite([ }); it('computeBuffers 1', function() { - var buffers = ExtentTessellator.computeBuffers({ + var buffers = ExtentGeometry.computeBuffers({ extent : new Extent(-2.0, -1.0, 0.0, 1.0), granularity : 1.0, generateTextureCoordinates : true @@ -67,7 +67,7 @@ defineSuite([ }); it('computeBuffers 2', function() { - var buffers = ExtentTessellator.computeBuffers({ + var buffers = ExtentGeometry.computeBuffers({ extent : new Extent(-2.0, -1.0, 0.0, 1.0), granularity : 1.0, generateTextureCoordinates : true, @@ -90,7 +90,7 @@ defineSuite([ vertices: [], indices: [] }; - ExtentTessellator.computeVertices(description); + ExtentGeometry.computeVertices(description); var length = description.vertices.length; var expectedNWCorner = Ellipsoid.WGS84.cartographicToCartesian(extent.getNorthwest()); var expectedSECorner = Ellipsoid.WGS84.cartographicToCartesian(extent.getSoutheast()); @@ -111,7 +111,7 @@ defineSuite([ vertices: [], indices: [] }; - ExtentTessellator.computeVertices(description); + ExtentGeometry.computeVertices(description); var length = description.vertices.length; expect(length).toEqual(9 * 3); expect(description.indices.length).toEqual(8 * 3); @@ -134,7 +134,7 @@ defineSuite([ vertices: [], indices: [] }; - ExtentTessellator.computeVertices(description); + ExtentGeometry.computeVertices(description); var length = description.vertices.length; expect(length).toEqual(9 * 3); expect(description.indices.length).toEqual(8 * 3); @@ -157,7 +157,7 @@ defineSuite([ vertices: [], indices: [] }; - ExtentTessellator.computeVertices(description); + ExtentGeometry.computeVertices(description); expect(description.vertices.length).toEqual(0); expect(description.indices.length).toEqual(0); }); @@ -175,7 +175,7 @@ defineSuite([ vertices: [], indices: [] }; - ExtentTessellator.computeVertices(description); + ExtentGeometry.computeVertices(description); expect(description.vertices.length).toEqual(0); expect(description.indices.length).toEqual(0); }); @@ -193,7 +193,7 @@ defineSuite([ vertices: [], indices: [] }; - ExtentTessellator.computeVertices(description); + ExtentGeometry.computeVertices(description); expect(description.vertices.length).toEqual(0); expect(description.indices.length).toEqual(0); }); @@ -211,7 +211,7 @@ defineSuite([ vertices: [], indices: [] }; - ExtentTessellator.computeVertices(description); + ExtentGeometry.computeVertices(description); expect(description.vertices.length).toEqual(0); expect(description.indices.length).toEqual(0); }); From 801bc56f87e9d6c076efe21af378a37eaf5cfcc4 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Wed, 22 May 2013 14:01:05 -0400 Subject: [PATCH 060/306] Remove unused code. --- Source/Core/ExtentGeometry.js | 130 ------------------------------- Specs/Core/ExtentGeometrySpec.js | 34 -------- 2 files changed, 164 deletions(-) diff --git a/Source/Core/ExtentGeometry.js b/Source/Core/ExtentGeometry.js index 002a58162a60..7187916d63a8 100644 --- a/Source/Core/ExtentGeometry.js +++ b/Source/Core/ExtentGeometry.js @@ -317,135 +317,5 @@ define([ return mesh; }; - /** - * Creates arrays of vertex attributes and indices from a cartographic extent. - * - * @param {Extent} description.extent A cartographic extent with north, south, east and west properties in radians. - * @param {Ellipsoid} [description.ellipsoid=Ellipsoid.WGS84] The ellipsoid on which the extent lies. - * @param {Number} [description.granularity=0.1] The distance, in radians, between each latitude and longitude. Determines the number of positions in the buffer. - * @param {Number} [description.surfaceHeight=0.0] The height from the surface of the ellipsoid. - * @param {Cartesian3} [description.relativetoCenter=Cartesian3.ZERO] The positions will be computed as worldPosition.subtract(relativeToCenter). - * @param {Boolean} [description.generateTextureCoordinates=false] Whether to generate texture coordinates. - * @param {Boolean} [description.interleaveTextureCoordinates=false] If texture coordinates are generated, whether to interleave the positions and texture coordinates in a single buffer. - * - * @exception {DeveloperError} description.extent is required and must have north, south, east and west attributes. - * @exception {DeveloperError} description.extent.north must be in the interval [-Pi/2, Pi/2]. - * @exception {DeveloperError} description.extent.south must be in the interval [-Pi/2, Pi/2]. - * @exception {DeveloperError} description.extent.east must be in the interval [-Pi, Pi]. - * @exception {DeveloperError} description.extent.west must be in the interval [-Pi, Pi]. - * @exception {DeveloperError} description.extent.north must be greater than extent.south. * - * @exception {DeveloperError} description.extent.east must be greater than extent.west. - * - * @return {Object} An object with flattened arrays for vertex attributes and indices. - * - * @example - * // Example 1: - * // Create a vertex array for a solid extent, with separate positions and texture coordinates. - * var buffers = ExtentGeometry.computeBuffers({ - * ellipsoid : ellipsoid, - * extent : extent, - * generateTextureCoordinates : true - * }); - * - * var datatype = ComponentDatatype.FLOAT; - * var usage = BufferUsage.STATIC_DRAW; - * var positionBuffer = context.createVertexBuffer(datatype.createTypedArray(buffers.positions), usage); - * var textureCoordinateBuffer = context.createVertexBuffer(datatype.createTypedArray(buffers.textureCoordinates), usage); - * attributes = [{ - * index : attributeIndices.position, - * vertexBuffer : positionBuffer, - * componentDatatype : datatype, - * componentsPerAttribute : 3 - * }, { - * index : attributeIndices.textureCoordinates, - * vertexBuffer : textureCoordinateBuffer, - * componentDatatype : datatype, - * componentsPerAttribute : 2 - * }]; - * var indexBuffer = context.createIndexBuffer(new Uint16Array(buffers.indices), usage, IndexDatatype.UNSIGNED_SHORT); - * var va = context.createVertexArray(attributes, indexBuffer); - * - * @example - * // Example 2: - * // Create a vertex array for a solid extent, with interleaved positions and texture coordinates. - * var buffers = ExtentGeometry.computeBuffers({ - * ellipsoid : ellipsoid, - * extent : extent, - * generateTextureCoordinates : true, - * interleaveTextureCoordinates : true - * }); - * - * var datatype = ComponentDatatype.FLOAT; - * var usage = BufferUsage.STATIC_DRAW; - * var typedArray = datatype.createTypedArray(buffers.vertices); - * var buffer = context.createVertexBuffer(typedArray, usage); - * var stride = 5 * datatype.sizeInBytes; - * var attributes = [{ - * index : attributeIndices.position3D, - * vertexBuffer : buffer, - * componentDatatype : datatype, - * componentsPerAttribute : 3, - * normalize : false, - * offsetInBytes : 0, - * strideInBytes : stride - * }, { - * index : attributeIndices.textureCoordinates, - * vertexBuffer : buffer, - * componentDatatype : datatype, - * componentsPerAttribute : 2, - * normalize : false, - * offsetInBytes : 3 * datatype.sizeInBytes, - * strideInBytes : stride - * }]; - * var indexBuffer = context.createIndexBuffer(new Uint16Array(buffers.indices), usage, IndexDatatype.UNSIGNED_SHORT); - * var vacontext.createVertexArray(attributes, indexBuffer); - */ - ExtentGeometry.computeBuffers = function(description) { - description = defaultValue(description, defaultValue.EMPTY_OBJECT); - - // make a copy of description to allow us to change values before passing to computeVertices - var computeVerticesDescription = clone(description); - - var extent = description.extent; - extent.validate(); - - var ellipsoid = defaultValue(description.ellipsoid, Ellipsoid.WGS84); - computeVerticesDescription.radiiSquared = ellipsoid.getRadiiSquared(); - computeVerticesDescription.relativeToCenter = defaultValue(description.relativeToCenter, Cartesian3.ZERO); - - var granularity = defaultValue(description.granularity, 0.1); - computeVerticesDescription.surfaceHeight = defaultValue(description.surfaceHeight, 0.0); - - computeVerticesDescription.width = Math.ceil((extent.east - extent.west) / granularity) + 1; - computeVerticesDescription.height = Math.ceil((extent.north - extent.south) / granularity) + 1; - - var vertices = []; - var indices = []; - var textureCoordinates = []; - - computeVerticesDescription.generateTextureCoordinates = defaultValue(description.generateTextureCoordinates, false); - computeVerticesDescription.interleaveTextureCoordinates = defaultValue(description.interleaveTextureCoordinates, false); - computeVerticesDescription.vertices = vertices; - computeVerticesDescription.textureCoordinates = textureCoordinates; - computeVerticesDescription.indices = indices; - - ExtentGeometry.computeVertices(computeVerticesDescription); - - var result = { - indices : indices - }; - - if (description.interleaveTextureCoordinates) { - result.vertices = vertices; - } else { - result.positions = vertices; - if (description.generateTextureCoordinates) { - result.textureCoordinates = textureCoordinates; - } - } - - return result; - }; - return ExtentGeometry; }); diff --git a/Specs/Core/ExtentGeometrySpec.js b/Specs/Core/ExtentGeometrySpec.js index 15032e5d386e..6c8f4608ee1e 100644 --- a/Specs/Core/ExtentGeometrySpec.js +++ b/Specs/Core/ExtentGeometrySpec.js @@ -44,40 +44,6 @@ defineSuite([ }) === 'undefined').toEqual(true); }); - it('computeBuffers 0', function() { - var buffers = ExtentGeometry.computeBuffers({ - extent : new Extent(-2.0, -1.0, 0.0, 1.0), - granularity : 1.0 - }); - - expect(buffers.positions.length).toEqual(9 * 3); - expect(buffers.indices.length).toEqual(8 * 3); - }); - - it('computeBuffers 1', function() { - var buffers = ExtentGeometry.computeBuffers({ - extent : new Extent(-2.0, -1.0, 0.0, 1.0), - granularity : 1.0, - generateTextureCoordinates : true - }); - - expect(buffers.positions.length).toEqual(9 * 3); - expect(buffers.textureCoordinates.length).toEqual(9 * 2); - expect(buffers.indices.length).toEqual(8 * 3); - }); - - it('computeBuffers 2', function() { - var buffers = ExtentGeometry.computeBuffers({ - extent : new Extent(-2.0, -1.0, 0.0, 1.0), - granularity : 1.0, - generateTextureCoordinates : true, - interleaveTextureCoordinates : true - }); - - expect(buffers.vertices.length).toEqual(9 * 3 + 9 * 2); - expect(buffers.indices.length).toEqual(8 * 3); - }); - it('compute vertices', function() { var extent = new Extent(-CesiumMath.PI, -CesiumMath.PI_OVER_TWO, CesiumMath.PI, CesiumMath.PI_OVER_TWO); var description = { From 353c4e5985f9eb3d9da8733a323e237abf31f98a Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Wed, 22 May 2013 14:38:30 -0400 Subject: [PATCH 061/306] Change ExtentTessellator to be ExtentGeometry (computes positions only). --- Apps/CesiumViewer/CesiumViewer.js | 3 +- Source/Core/ExtentGeometry.js | 355 +++++++++++++----------------- 2 files changed, 159 insertions(+), 199 deletions(-) diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index 73767f8cc5aa..a7eef277b29b 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -72,7 +72,8 @@ define([ var scene = widget.scene; - var mesh = ExtentGeometry.compute({ + var mesh = new ExtentGeometry({ + vertexFormat : VertexFormat.POSITION_ONLY, extent : new Extent( CesiumMath.toRadians(-180.0), CesiumMath.toRadians(50.0), diff --git a/Source/Core/ExtentGeometry.js b/Source/Core/ExtentGeometry.js index 7187916d63a8..d12db59c4bfc 100644 --- a/Source/Core/ExtentGeometry.js +++ b/Source/Core/ExtentGeometry.js @@ -2,44 +2,41 @@ define([ './clone', './defaultValue', + './BoundingSphere', + './Cartesian3', + './Cartographic', + './ComponentDatatype', './DeveloperError', - './Math', './Ellipsoid', './Extent', - './Cartesian3', - './Cartographic', - './Matrix2', './GeographicProjection', - './ComponentDatatype', - './PrimitiveType', - './Geometry', './GeometryAttribute', - './GeometryIndices' + './GeometryIndices', + './Math', + './Matrix2', + './Matrix4', + './PrimitiveType', + './VertexFormat' ], function( clone, defaultValue, + BoundingSphere, + Cartesian3, + Cartographic, + ComponentDatatype, DeveloperError, - CesiumMath, Ellipsoid, Extent, - Cartesian3, - Cartographic, - Matrix2, GeographicProjection, - ComponentDatatype, - PrimitiveType, - Geometry, GeometryAttribute, - GeometryIndices) { + GeometryIndices, + CesiumMath, + Matrix2, + Matrix4, + PrimitiveType, + VertexFormat) { "use strict"; - /** - * Contains class functions to create a mesh or vertex array from a cartographic extent. - * - * @exports ExtentGeometry - */ - var ExtentGeometry = {}; - function isValidLatLon(latitude, longitude) { if (latitude < -CesiumMath.PI_OVER_TWO || latitude > CesiumMath.PI_OVER_TWO) { return false; @@ -49,54 +46,70 @@ define([ } return true; } - /** - * Compute vertices from a cartographic extent. This function is different from - * {@link ExtentGeometry#compute} and {@link ExtentGeometry#computeBuffers} - * in that it assumes that you have already allocated output arrays of the correct size. - * - * @param {Extent} description.extent A cartographic extent with north, south, east and west properties in radians. - * @param {Number} description.rotation The rotation of the extent in radians. - * @param {Number} description.width The number of vertices in the longitude direction. - * @param {Number} description.height The number of vertices in the latitude direction. - * @param {Number} description.surfaceHeight The height from the surface of the ellipsoid. - * @param {Boolean} description.generateTextureCoordinates Whether to generate texture coordinates. - * @param {Boolean} description.interleaveTextureCoordinates Whether to interleave the texture coordinates into the vertex array. - * @param {Cartesian3} description.relativetoCenter The positions will be computed as worldPosition.subtract(relativeToCenter). - * @param {Cartesian3} description.radiiSquared The radii squared of the ellipsoid to use. - * @param {Array|Float32Array} description.vertices The array to use to store computed vertices. - * @param {Array|Float32Array} description.textureCoordinates The array to use to store computed texture coordinates, unless interleaved. - * @param {Array|Float32Array} [description.indices] The array to use to store computed indices. If undefined, indices will be not computed. - */ + var nw = new Cartesian3(); var nwCartographic = new Cartographic(); var centerCartographic = new Cartographic(); var center = new Cartesian3(); var rotationMatrix = new Matrix2(); var proj = new GeographicProjection(); - ExtentGeometry.computeVertices = function(description) { - description = defaultValue(description, defaultValue.EMPTY_OBJECT); - var extent = description.extent; + + /** + * Creates geometry for a cartographic extent of an ellipsoid centered at the origin. + * + * @param {Extent} description.extent A cartographic extent with north, south, east and west properties in radians. + * @param {Ellipsoid} [description.ellipsoid=Ellipsoid.WGS84] The ellipsoid on which the extent lies. + * @param {Number} [description.granularity=0.1] The distance, in radians, between each latitude and longitude. Determines the number of positions in the buffer. + * @param {Number} [description.surfaceHeight=0.0] The height from the surface of the ellipsoid. + * @param {Cartesian3} [description.relativetoCenter=Cartesian3.ZERO] The positions will be computed as worldPosition.subtract(relativeToCenter). + * @param {Number} [description.rotation=0.0] The rotation of the extent in radians. + * + * @exception {DeveloperError} description.extent is required and must have north, south, east and west attributes. + * @exception {DeveloperError} description.extent.north must be in the interval [-Pi/2, Pi/2]. + * @exception {DeveloperError} description.extent.south must be in the interval [-Pi/2, Pi/2]. + * @exception {DeveloperError} description.extent.east must be in the interval [-Pi, Pi]. + * @exception {DeveloperError} description.extent.west must be in the interval [-Pi, Pi]. + * @exception {DeveloperError} description.extent.north must be greater than extent.south. + * @exception {DeveloperError} description.extent.east must be greater than extent.west. + * @exception {DeveloperError} description.context is required. + * + * @see Extent + * + * @example + * var extent = new ExtentGeometry({ + * ellipsoid : Ellipsoid.WGS84, + * extent : new Extent( + * CesiumMath.toRadians(-80.0), + * CesiumMath.toRadians(39.0), + * CesiumMath.toRadians(-74.0), + * CesiumMath.toRadians(42.0) + * ), + * granularity : 0.01, + * surfaceHeight : 10000.0 + * }); + */ + var ExtentGeometry = function(options) { + options = defaultValue(options, defaultValue.EMPTY_OBJECT); + + var extent = options.extent; extent.validate(); - var rotation = description.rotation; - var surfaceHeight = description.surfaceHeight; - var width = description.width; - var height = description.height; + var granularity = defaultValue(options.granularity, 0.1); + var width = Math.ceil((extent.east - extent.west) / granularity) + 1; + var height = Math.ceil((extent.north - extent.south) / granularity) + 1; var granularityX = (extent.east - extent.west) / (width - 1); var granularityY = (extent.north - extent.south) / (height - 1); - var generateTextureCoordinates = description.generateTextureCoordinates; - var interleaveTextureCoordinates = description.interleaveTextureCoordinates; - var relativeToCenter = description.relativeToCenter; - var vertices = description.vertices; - var textureCoordinates = description.textureCoordinates; - var indices = description.indices; - - var radiiSquared = description.radiiSquared; + var ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84); + var radiiSquared = ellipsoid.getRadiiSquared(); var radiiSquaredX = radiiSquared.x; var radiiSquaredY = radiiSquared.y; var radiiSquaredZ = radiiSquared.z; + var relativeToCenter = defaultValue(options.relativeToCenter, Cartesian3.ZERO); + var surfaceHeight = defaultValue(options.surfaceHeight, 0.0); + var rotation = defaultValue(options.rotation, 0.0); + var cos = Math.cos; var sin = Math.sin; var sqrt = Math.sqrt; @@ -105,17 +118,10 @@ define([ var lonScalar = 1.0 / (extent.east - extent.west); var latScalar = 1.0 / (extent.north - extent.south); - var vertexArrayIndex = 0; - var textureCoordinatesIndex = 0; - extent.getNorthwest(nwCartographic); extent.getCenter(centerCartographic); var latitude, longitude; - if (typeof rotation === 'undefined') { - rotation = 0; - } - var granYCos = granularityY * cos(rotation); var granYSin = granularityY * sin(rotation); var granXCos = granularityX * cos(rotation); @@ -145,6 +151,14 @@ define([ } } + var vertexFormat = defaultValue(options.vertexFormat, VertexFormat.DEFAULT); + var attributes = {}; + + var positionIndex = 0; + var stIndex = 0; + + var positions = []; + for ( var row = 0; row < height; ++row) { for ( var col = 0; col < width; ++col) { latitude = nwCartographic.latitude - granYCos*row + col*granXSin; @@ -166,155 +180,100 @@ define([ var rSurfaceY = kY / gamma; var rSurfaceZ = kZ / gamma; - vertices[vertexArrayIndex++] = rSurfaceX + nX * surfaceHeight - relativeToCenter.x; - vertices[vertexArrayIndex++] = rSurfaceY + nY * surfaceHeight - relativeToCenter.y; - vertices[vertexArrayIndex++] = rSurfaceZ + nZ * surfaceHeight - relativeToCenter.z; + positions[positionIndex++] = rSurfaceX + nX * surfaceHeight - relativeToCenter.x; + positions[positionIndex++] = rSurfaceY + nY * surfaceHeight - relativeToCenter.y; + positions[positionIndex++] = rSurfaceZ + nZ * surfaceHeight - relativeToCenter.z; + /* if (generateTextureCoordinates) { - var u = (longitude - extent.west) * lonScalar; - var v = (latitude - extent.south) * latScalar; - - if (interleaveTextureCoordinates) { - vertices[vertexArrayIndex++] = u; - vertices[vertexArrayIndex++] = v; - } else { - textureCoordinates[textureCoordinatesIndex++] = u; - textureCoordinates[textureCoordinatesIndex++] = v; - } + textureCoordinates[stIndex++] = (longitude - extent.west) * lonScalar; + textureCoordinates[stIndex++] = (latitude - extent.south) * latScalar; } + */ } } - if (typeof indices !== 'undefined') { - var index = 0; - var indicesIndex = 0; - for ( var i = 0; i < height - 1; ++i) { - for ( var j = 0; j < width - 1; ++j) { - var upperLeft = index; - var lowerLeft = upperLeft + width; - var lowerRight = lowerLeft + 1; - var upperRight = upperLeft + 1; - - indices[indicesIndex++] = upperLeft; - indices[indicesIndex++] = lowerLeft; - indices[indicesIndex++] = upperRight; - indices[indicesIndex++] = upperRight; - indices[indicesIndex++] = lowerLeft; - indices[indicesIndex++] = lowerRight; - - ++index; - } - ++index; - } - } - }; - - /** - * Creates a mesh from a cartographic extent. - * - * @param {Extent} description.extent A cartographic extent with north, south, east and west properties in radians. - * @param {Ellipsoid} [description.ellipsoid=Ellipsoid.WGS84] The ellipsoid on which the extent lies. - * @param {Number} [description.granularity=0.1] The distance, in radians, between each latitude and longitude. Determines the number of positions in the buffer. - * @param {Number} [description.surfaceHeight=0.0] The height from the surface of the ellipsoid. - * @param {Cartesian3} [description.relativetoCenter=Cartesian3.ZERO] The positions will be computed as worldPosition.subtract(relativeToCenter). - * @param {Boolean} [description.generateTextureCoordinates=false] Whether to generate texture coordinates. - * - * @exception {DeveloperError} description.extent is required and must have north, south, east and west attributes. - * @exception {DeveloperError} description.extent.north must be in the interval [-Pi/2, Pi/2]. - * @exception {DeveloperError} description.extent.south must be in the interval [-Pi/2, Pi/2]. - * @exception {DeveloperError} description.extent.east must be in the interval [-Pi, Pi]. - * @exception {DeveloperError} description.extent.west must be in the interval [-Pi, Pi]. - * @exception {DeveloperError} description.extent.north must be greater than extent.south. - * @exception {DeveloperError} description.extent.east must be greater than extent.west. - * @exception {DeveloperError} description.context is required. - * - * @return {Object} A mesh containing attributes for positions, possibly texture coordinates and indices - * from the extent for creating a vertex array. (returns undefined if no indices are found) - * - * @see Context#createVertexArrayFromMesh - * @see GeometryFilters.createAttributeIndices - * @see GeometryFilters.toWireframe - * @see Extent - * - * @example - * // Create a vertex array for rendering a wireframe extent. - * var mesh = ExtentGeometry.compute({ - * ellipsoid : Ellipsoid.WGS84, - * extent : new Extent( - * CesiumMath.toRadians(-80.0), - * CesiumMath.toRadians(39.0), - * CesiumMath.toRadians(-74.0), - * CesiumMath.toRadians(42.0) - * ), - * granularity : 0.01, - * surfaceHeight : 10000.0 - * }); - * mesh = GeometryFilters.toWireframe(mesh); - * var va = context.createVertexArrayFromMesh({ - * mesh : mesh, - * attributeIndices : GeometryFilters.createAttributeIndices(mesh) - * }); - */ - ExtentGeometry.compute = function(description) { - description = defaultValue(description, defaultValue.EMPTY_OBJECT); - - // make a copy of description to allow us to change values before passing to computeVertices - var computeVerticesDescription = clone(description); - - var extent = description.extent; - extent.validate(); - - var ellipsoid = defaultValue(description.ellipsoid, Ellipsoid.WGS84); - computeVerticesDescription.radiiSquared = ellipsoid.getRadiiSquared(); - computeVerticesDescription.relativeToCenter = defaultValue(description.relativeToCenter, Cartesian3.ZERO); - - var granularity = defaultValue(description.granularity, 0.1); - computeVerticesDescription.surfaceHeight = defaultValue(description.surfaceHeight, 0.0); - - computeVerticesDescription.width = Math.ceil((extent.east - extent.west) / granularity) + 1; - computeVerticesDescription.height = Math.ceil((extent.north - extent.south) / granularity) + 1; - - var vertices = []; var indices = []; - var textureCoordinates = []; - - computeVerticesDescription.generateTextureCoordinates = defaultValue(computeVerticesDescription.generateTextureCoordinates, false); - computeVerticesDescription.interleaveTextureCoordinates = false; - computeVerticesDescription.vertices = vertices; - computeVerticesDescription.textureCoordinates = textureCoordinates; - computeVerticesDescription.indices = indices; + var index = 0; + var indicesIndex = 0; + for ( var i = 0; i < height - 1; ++i) { + for ( var j = 0; j < width - 1; ++j) { + var upperLeft = index; + var lowerLeft = upperLeft + width; + var lowerRight = lowerLeft + 1; + var upperRight = upperLeft + 1; + + indices[indicesIndex++] = upperLeft; + indices[indicesIndex++] = lowerLeft; + indices[indicesIndex++] = upperRight; + indices[indicesIndex++] = upperRight; + indices[indicesIndex++] = lowerLeft; + indices[indicesIndex++] = lowerRight; - ExtentGeometry.computeVertices(computeVerticesDescription); - - if (indices.length === 0) { - return undefined; + ++index; + } + ++index; } - var mesh = new Geometry({ - attributes : {}, - indexLists : [new GeometryIndices({ - primitiveType : PrimitiveType.TRIANGLES, - values : indices - })] - }); - - var positionName = defaultValue(description.positionName, 'position'); - mesh.attributes[positionName] = new GeometryAttribute({ - componentDatatype : ComponentDatatype.FLOAT, - componentsPerAttribute : 3, - values : vertices - }); - - if (description.generateTextureCoordinates) { - var textureCoordinatesName = defaultValue(description.textureCoordinatesName, 'textureCoordinates'); - mesh.attributes[textureCoordinatesName] = new GeometryAttribute({ + if (vertexFormat.position) { + attributes.position = new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, - componentsPerAttribute : 2, - values : textureCoordinates + componentsPerAttribute : 3, + values : positions }); } - return mesh; + /* + attributes.st = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 2, + values : textureCoordinates + }); + */ + + /** + * An object containing {@link GeometryAttribute} properties named after each of the + * true values of the {@link VertexFormat} option. + * + * @type Object + */ + this.attributes = attributes; + + /** + * An array of {@link GeometryIndices} defining primitives. + * + * @type Array + */ + this.indexLists = [ + new GeometryIndices({ + primitiveType : PrimitiveType.TRIANGLES, + values : indices + }) + ]; + + /** + * A tight-fitting bounding sphere that encloses the vertices of the geometry. + * + * @type BoundingSphere + */ + this.boundingSphere = BoundingSphere.fromExtent3D(extent, ellipsoid); // TODO: surface height + + /** + * The 4x4 transformation matrix that transforms the geometry from model to world coordinates. + * When this is the identity matrix, the geometry is drawn in world coordinates, i.e., Earth's WGS84 coordinates. + * Local reference frames can be used by providing a different transformation matrix, like that returned + * by {@link Transforms.eastNorthUpToFixedFrame}. + * + * @type Matrix4 + * + * @see Transforms.eastNorthUpToFixedFrame + */ + this.modelMatrix = defaultValue(options.modelMatrix, Matrix4.IDENTITY.clone()); + + /** + * DOC_TBA + */ + this.pickData = options.pickData; }; return ExtentGeometry; From c721218e3b76309f903adb2a1bd5aa066923fdc5 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Wed, 22 May 2013 14:54:27 -0400 Subject: [PATCH 062/306] Add texture coordinates to extent geometry. --- Apps/CesiumViewer/CesiumViewer.js | 26 +++++++++++++++++++++-- Source/Core/ExtentGeometry.js | 34 ++++++++++++++++++------------- 2 files changed, 44 insertions(+), 16 deletions(-) diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index a7eef277b29b..e14ef8f4bbdf 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -72,8 +72,25 @@ define([ var scene = widget.scene; + var imageMaterial = new Material({ + context : scene.getContext(), + fabric : { + type : 'Image', + uniforms : { + image : '../Sandcastle/images/Cesium_Logo_Color.jpg' + } + } + }); + var imageAppearance = new Appearance({ + material : imageMaterial, + renderState : { + depthTest : { + enabled : true + } + } + }); var mesh = new ExtentGeometry({ - vertexFormat : VertexFormat.POSITION_ONLY, + vertexFormat : VertexFormat.DEFAULT, extent : new Extent( CesiumMath.toRadians(-180.0), CesiumMath.toRadians(50.0), @@ -82,6 +99,11 @@ define([ granularity : 0.006 // More than 64K vertices }); mesh.pickData = 'mesh'; + var extent = new Primitive({ + geometries : [mesh], + appearance : imageAppearance + }); + widget.scene.getPrimitives().add(extent); var mesh2 = new EllipsoidGeometry({ ellipsoid : new Ellipsoid(500000.0, 500000.0, 1000000.0), @@ -98,7 +120,7 @@ define([ pickData : 'mesh3' }); var primitive = new Primitive({ - geometries : [mesh, mesh2, mesh3], + geometries : [/*mesh,*/ mesh2, mesh3], appearance : Appearance.CLOSED_TRANSLUCENT }); widget.scene.getPrimitives().add(primitive); diff --git a/Source/Core/ExtentGeometry.js b/Source/Core/ExtentGeometry.js index d12db59c4bfc..39711bef86cc 100644 --- a/Source/Core/ExtentGeometry.js +++ b/Source/Core/ExtentGeometry.js @@ -157,7 +157,9 @@ define([ var positionIndex = 0; var stIndex = 0; - var positions = []; + var size = width * height; + var positions = (vertexFormat.position) ? new Array(size * 3) : undefined; + var textureCoordinates = (vertexFormat.st) ? new Array(size * 2) : undefined; for ( var row = 0; row < height; ++row) { for ( var col = 0; col < width; ++col) { @@ -180,16 +182,20 @@ define([ var rSurfaceY = kY / gamma; var rSurfaceZ = kZ / gamma; - positions[positionIndex++] = rSurfaceX + nX * surfaceHeight - relativeToCenter.x; - positions[positionIndex++] = rSurfaceY + nY * surfaceHeight - relativeToCenter.y; - positions[positionIndex++] = rSurfaceZ + nZ * surfaceHeight - relativeToCenter.z; + var x = rSurfaceX + nX * surfaceHeight - relativeToCenter.x; + var y = rSurfaceY + nY * surfaceHeight - relativeToCenter.y; + var z = rSurfaceZ + nZ * surfaceHeight - relativeToCenter.z; - /* - if (generateTextureCoordinates) { + if (vertexFormat.position) { + positions[positionIndex++] = x; + positions[positionIndex++] = y; + positions[positionIndex++] = z; + } + + if (vertexFormat.st) { textureCoordinates[stIndex++] = (longitude - extent.west) * lonScalar; textureCoordinates[stIndex++] = (latitude - extent.south) * latScalar; } - */ } } @@ -223,13 +229,13 @@ define([ }); } - /* - attributes.st = new GeometryAttribute({ - componentDatatype : ComponentDatatype.FLOAT, - componentsPerAttribute : 2, - values : textureCoordinates - }); - */ + if (vertexFormat.st) { + attributes.st = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 2, + values : textureCoordinates + }); + } /** * An object containing {@link GeometryAttribute} properties named after each of the From de548d68726a240dd4723fca22c3e0a7023405b9 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Wed, 22 May 2013 15:18:43 -0400 Subject: [PATCH 063/306] Add normal, tangent, and binormal vertex attributes to extent geometry. --- Apps/CesiumViewer/CesiumViewer.js | 79 ++++++++++++------------------- Source/Core/EllipsoidGeometry.js | 2 +- Source/Core/ExtentGeometry.js | 73 ++++++++++++++++++++++++---- 3 files changed, 96 insertions(+), 58 deletions(-) diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index e14ef8f4bbdf..9eadd60d68b0 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -72,23 +72,41 @@ define([ var scene = widget.scene; - var imageMaterial = new Material({ - context : scene.getContext(), + var m = new Material({ + context : widget.scene.getContext(), fabric : { - type : 'Image', - uniforms : { - image : '../Sandcastle/images/Cesium_Logo_Color.jpg' + materials : { + diffuseMaterial : { + type : 'DiffuseMap', + uniforms : { + image : '../Sandcastle/images/bumpmap.png' + } + }, + normalMap : { + type : 'NormalMap', + uniforms : { + image : '../Sandcastle/images/normalmap.png', + strength : 0.6 + } + } + }, + components : { + diffuse : 'diffuseMaterial.diffuse', + specular : 0.01, + normal : 'normalMap.normal' } } - }); - var imageAppearance = new Appearance({ - material : imageMaterial, - renderState : { - depthTest : { - enabled : true - } + }); + var rs = { + depthTest : { + enabled : true } + }; + var appearance = new Appearance({ + material : m, + renderState : rs }); + var mesh = new ExtentGeometry({ vertexFormat : VertexFormat.DEFAULT, extent : new Extent( @@ -101,7 +119,7 @@ define([ mesh.pickData = 'mesh'; var extent = new Primitive({ geometries : [mesh], - appearance : imageAppearance + appearance : appearance }); widget.scene.getPrimitives().add(extent); @@ -125,41 +143,6 @@ define([ }); widget.scene.getPrimitives().add(primitive); - var m = new Material({ - context : widget.scene.getContext(), - fabric : { - materials : { - diffuseMaterial : { - type : 'DiffuseMap', - uniforms : { - image : '../Sandcastle/images/bumpmap.png' - } - }, - normalMap : { - type : 'NormalMap', - uniforms : { - image : '../Sandcastle/images/normalmap.png', - strength : 0.6 - } - } - }, - components : { - diffuse : 'diffuseMaterial.diffuse', - specular : 0.01, - normal : 'normalMap.normal' - } - } - }); - var rs = { - depthTest : { - enabled : true - } - }; - var appearance = new Appearance({ - material : m, - renderState : rs - }); - var mesh4 = new EllipsoidGeometry({ vertexFormat : VertexFormat.ALL, ellipsoid : new Ellipsoid(1000000.0, 500000.0, 500000.0), diff --git a/Source/Core/EllipsoidGeometry.js b/Source/Core/EllipsoidGeometry.js index d14fe63f1ca5..cc988658d605 100644 --- a/Source/Core/EllipsoidGeometry.js +++ b/Source/Core/EllipsoidGeometry.js @@ -263,7 +263,7 @@ define([ for (i = j = 0; i < length; ++i, j += 3) { ellipsoid.geodeticSurfaceNormal(positions[i], normal); Cartesian3.cross(Cartesian3.UNIT_Z, normal, tangent); - Cartesian3.cross(tangent, normal, binormal); + Cartesian3.cross(normal, tangent, binormal); if (vertexFormat.normal) { normals[j] = normal.x; diff --git a/Source/Core/ExtentGeometry.js b/Source/Core/ExtentGeometry.js index 39711bef86cc..b9da7d09abe4 100644 --- a/Source/Core/ExtentGeometry.js +++ b/Source/Core/ExtentGeometry.js @@ -53,6 +53,10 @@ define([ var center = new Cartesian3(); var rotationMatrix = new Matrix2(); var proj = new GeographicProjection(); + var position = new Cartesian3(); + var normal = new Cartesian3(); + var tangent = new Cartesian3(); + var binormal = new Cartesian3(); /** * Creates geometry for a cartographic extent of an ellipsoid centered at the origin. @@ -61,7 +65,6 @@ define([ * @param {Ellipsoid} [description.ellipsoid=Ellipsoid.WGS84] The ellipsoid on which the extent lies. * @param {Number} [description.granularity=0.1] The distance, in radians, between each latitude and longitude. Determines the number of positions in the buffer. * @param {Number} [description.surfaceHeight=0.0] The height from the surface of the ellipsoid. - * @param {Cartesian3} [description.relativetoCenter=Cartesian3.ZERO] The positions will be computed as worldPosition.subtract(relativeToCenter). * @param {Number} [description.rotation=0.0] The rotation of the extent in radians. * * @exception {DeveloperError} description.extent is required and must have north, south, east and west attributes. @@ -71,7 +74,6 @@ define([ * @exception {DeveloperError} description.extent.west must be in the interval [-Pi, Pi]. * @exception {DeveloperError} description.extent.north must be greater than extent.south. * @exception {DeveloperError} description.extent.east must be greater than extent.west. - * @exception {DeveloperError} description.context is required. * * @see Extent * @@ -106,7 +108,6 @@ define([ var radiiSquaredY = radiiSquared.y; var radiiSquaredZ = radiiSquared.z; - var relativeToCenter = defaultValue(options.relativeToCenter, Cartesian3.ZERO); var surfaceHeight = defaultValue(options.surfaceHeight, 0.0); var rotation = defaultValue(options.rotation, 0.0); @@ -156,10 +157,16 @@ define([ var positionIndex = 0; var stIndex = 0; + var normalIndex = 0; + var tangentIndex = 0; + var binormalIndex = 0; var size = width * height; var positions = (vertexFormat.position) ? new Array(size * 3) : undefined; var textureCoordinates = (vertexFormat.st) ? new Array(size * 2) : undefined; + var normals = (vertexFormat.normal) ? new Array(size * 3) : undefined; + var tangents = (vertexFormat.tangent) ? new Array(size * 3) : undefined; + var binormals = (vertexFormat.binormal) ? new Array(size * 3) : undefined; for ( var row = 0; row < height; ++row) { for ( var col = 0; col < width; ++col) { @@ -182,20 +189,44 @@ define([ var rSurfaceY = kY / gamma; var rSurfaceZ = kZ / gamma; - var x = rSurfaceX + nX * surfaceHeight - relativeToCenter.x; - var y = rSurfaceY + nY * surfaceHeight - relativeToCenter.y; - var z = rSurfaceZ + nZ * surfaceHeight - relativeToCenter.z; + position.x = rSurfaceX + nX * surfaceHeight; + position.y = rSurfaceY + nY * surfaceHeight; + position.z = rSurfaceZ + nZ * surfaceHeight; if (vertexFormat.position) { - positions[positionIndex++] = x; - positions[positionIndex++] = y; - positions[positionIndex++] = z; + positions[positionIndex++] = position.x; + positions[positionIndex++] = position.y; + positions[positionIndex++] = position.z; } if (vertexFormat.st) { textureCoordinates[stIndex++] = (longitude - extent.west) * lonScalar; textureCoordinates[stIndex++] = (latitude - extent.south) * latScalar; } + + if (vertexFormat.normal || vertexFormat.tangent || vertexFormat.binormal) { + ellipsoid.geodeticSurfaceNormal(position, normal); + Cartesian3.cross(Cartesian3.UNIT_Z, normal, tangent); + Cartesian3.cross(normal, tangent, binormal); + + if (vertexFormat.normal) { + normals[normalIndex++] = normal.x; + normals[normalIndex++] = normal.y; + normals[normalIndex++] = normal.z; + } + + if (vertexFormat.tangent) { + tangents[tangentIndex++] = tangent.x; + tangents[tangentIndex++] = tangent.y; + tangents[tangentIndex++] = tangent.z; + } + + if (vertexFormat.binormal) { + binormals[binormalIndex++] = binormal.x; + binormals[binormalIndex++] = binormal.y; + binormals[binormalIndex++] = binormal.z; + } + } } } @@ -237,6 +268,30 @@ define([ }); } + if (vertexFormat.normal) { + attributes.normal = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : normals + }); + } + + if (vertexFormat.tangent) { + attributes.tangent = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : tangents + }); + } + + if (vertexFormat.binormal) { + attributes.binormal = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : binormals + }); + } + /** * An object containing {@link GeometryAttribute} properties named after each of the * true values of the {@link VertexFormat} option. From bdd45dcb7e6a31db65406401106784cc6368c6d3 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Wed, 22 May 2013 15:39:42 -0400 Subject: [PATCH 064/306] Remove 'configureExtent' from Polygon. Revert CesiumViewer. --- Apps/CesiumViewer/CesiumViewer.js | 66 ++++++++++----------- Source/Scene/Polygon.js | 52 +---------------- Specs/Scene/PolygonSpec.js | 96 ------------------------------- 3 files changed, 31 insertions(+), 183 deletions(-) diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index 9eadd60d68b0..756f594e2043 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -72,6 +72,36 @@ define([ var scene = widget.scene; + var mesh = new ExtentGeometry({ + extent : new Extent( + CesiumMath.toRadians(-180.0), + CesiumMath.toRadians(50.0), + CesiumMath.toRadians(180.0), + CesiumMath.toRadians(90.0)), + granularity : 0.006 // More than 64K vertices + }); + mesh.pickData = 'mesh'; + + var mesh2 = new EllipsoidGeometry({ + ellipsoid : new Ellipsoid(500000.0, 500000.0, 1000000.0), + modelMatrix : Matrix4.multiplyByTranslation(Transforms.eastNorthUpToFixedFrame( + Ellipsoid.WGS84.cartographicToCartesian(Cartographic.fromDegrees(-95.59777, 40.03883))), new Cartesian3(0.0, 0.0, 500000.0)), + pickData : 'mesh2' + }); + + var mesh3 = new BoxGeometry({ + vertexFormat : VertexFormat.POSITION_ONLY, + dimensions : new Cartesian3(1000000.0, 1000000.0, 2000000.0), + modelMatrix : Matrix4.multiplyByTranslation(Transforms.eastNorthUpToFixedFrame( + Ellipsoid.WGS84.cartographicToCartesian(Cartographic.fromDegrees(-75.59777, 40.03883))), new Cartesian3(0.0, 0.0, 3000000.0)), + pickData : 'mesh3' + }); + var primitive = new Primitive({ + geometries : [mesh, mesh2, mesh3], + appearance : Appearance.CLOSED_TRANSLUCENT + }); + widget.scene.getPrimitives().add(primitive); + var m = new Material({ context : widget.scene.getContext(), fabric : { @@ -107,42 +137,6 @@ define([ renderState : rs }); - var mesh = new ExtentGeometry({ - vertexFormat : VertexFormat.DEFAULT, - extent : new Extent( - CesiumMath.toRadians(-180.0), - CesiumMath.toRadians(50.0), - CesiumMath.toRadians(180.0), - CesiumMath.toRadians(90.0)), - granularity : 0.006 // More than 64K vertices - }); - mesh.pickData = 'mesh'; - var extent = new Primitive({ - geometries : [mesh], - appearance : appearance - }); - widget.scene.getPrimitives().add(extent); - - var mesh2 = new EllipsoidGeometry({ - ellipsoid : new Ellipsoid(500000.0, 500000.0, 1000000.0), - modelMatrix : Matrix4.multiplyByTranslation(Transforms.eastNorthUpToFixedFrame( - Ellipsoid.WGS84.cartographicToCartesian(Cartographic.fromDegrees(-95.59777, 40.03883))), new Cartesian3(0.0, 0.0, 500000.0)), - pickData : 'mesh2' - }); - - var mesh3 = new BoxGeometry({ - vertexFormat : VertexFormat.POSITION_ONLY, - dimensions : new Cartesian3(1000000.0, 1000000.0, 2000000.0), - modelMatrix : Matrix4.multiplyByTranslation(Transforms.eastNorthUpToFixedFrame( - Ellipsoid.WGS84.cartographicToCartesian(Cartographic.fromDegrees(-75.59777, 40.03883))), new Cartesian3(0.0, 0.0, 3000000.0)), - pickData : 'mesh3' - }); - var primitive = new Primitive({ - geometries : [/*mesh,*/ mesh2, mesh3], - appearance : Appearance.CLOSED_TRANSLUCENT - }); - widget.scene.getPrimitives().add(primitive); - var mesh4 = new EllipsoidGeometry({ vertexFormat : VertexFormat.ALL, ellipsoid : new Ellipsoid(1000000.0, 500000.0, 500000.0), diff --git a/Source/Scene/Polygon.js b/Source/Scene/Polygon.js index 1e0ccb1fff88..8c24ff89e9b6 100644 --- a/Source/Scene/Polygon.js +++ b/Source/Scene/Polygon.js @@ -19,7 +19,6 @@ define([ '../Core/EllipsoidTangentPlane', '../Core/PolygonPipeline', '../Core/WindingOrder', - '../Core/ExtentGeometry', '../Core/Intersect', '../Core/Queue', '../Core/Matrix3', @@ -55,7 +54,6 @@ define([ EllipsoidTangentPlane, PolygonPipeline, WindingOrder, - ExtentGeometry, Intersect, Queue, Matrix3, @@ -210,7 +208,6 @@ define([ this._positions = undefined; this._textureRotationAngle = undefined; - this._extent = undefined; this._polygonHierarchy = undefined; this._createVertexArray = false; @@ -319,7 +316,6 @@ define([ } this.height = defaultValue(height, 0.0); this._textureRotationAngle = defaultValue(textureRotationAngle, 0.0); - this._extent = undefined; this._polygonHierarchy = undefined; this._positions = positions; this._createVertexArray = true; @@ -413,41 +409,10 @@ define([ this.height = defaultValue(height, 0.0); this._textureRotationAngle = defaultValue(textureRotationAngle, 0.0); this._positions = undefined; - this._extent = undefined; this._polygonHierarchy = polygons; this._createVertexArray = true; }; - /** - * DOC_TBA - * - * @memberof Polygon - * - * @param {extent} extent. The cartographic extent of the tile, with north, south, east and - * west properties in radians. - * - * @param {double} [height=0.0]. The height of the cartographic extent. - * @param {double} [rotation=0.0]. The rotation of the cartographic extent. - * @example - * polygon.configureExtent(new Extent( - * CesiumMath.toRadians(0.0), - * CesiumMath.toRadians(0.0), - * CesiumMath.toRadians(10.0), - * CesiumMath.toRadians(10.0)), - * 0.0, - * CesiumMath.toRadians(45.0), - * ); - */ - Polygon.prototype.configureExtent = function(extent, height, rotation) { - this._extent = extent; - this.height = defaultValue(height, 0.0); - this.rotation = defaultValue(rotation, 0.0); - this._textureRotationAngle = undefined; - this._positions = undefined; - this._polygonHierarchy = undefined; - this._createVertexArray = true; - }; - var appendTextureCoordinatesCartesian2 = new Cartesian2(); var appendTextureCoordinatesCartesian3 = new Cartesian3(); var appendTextureCoordinatesQuaternion = new Quaternion(); @@ -564,22 +529,7 @@ define([ var meshes = []; var mesh; - if ((typeof polygon._extent !== 'undefined') && !polygon._extent.isEmpty()) { - mesh = ExtentGeometry.compute({ - extent : polygon._extent, - rotation : polygon.rotation, - generateTextureCoordinates : true - }); - if (typeof mesh !== 'undefined') { - meshes.push(mesh); - } - polygon._boundingVolume = BoundingSphere.fromExtent3D(polygon._extent, polygon._ellipsoid, polygon._boundingVolume); - if (polygon._mode !== SceneMode.SCENE3D) { - polygon._boundingVolume2D = BoundingSphere.fromExtent2D(polygon._extent, polygon._projection, polygon._boundingVolume2D); - var center2D = polygon._boundingVolume2D.center; - polygon._boundingVolume2D.center = new Cartesian3(0.0, center2D.x, center2D.y); - } - } else if (typeof polygon._positions !== 'undefined') { + if (typeof polygon._positions !== 'undefined') { polygon._boundingVolume = BoundingSphere.fromPoints(polygon._positions, polygon._boundingVolume); mesh = createMeshFromPositions(polygon, polygon._positions, polygon._textureRotationAngle, polygon._boundingVolume); if (typeof mesh !== 'undefined') { diff --git a/Specs/Scene/PolygonSpec.js b/Specs/Scene/PolygonSpec.js index 01e1021d1145..d1306a5c202a 100644 --- a/Specs/Scene/PolygonSpec.js +++ b/Specs/Scene/PolygonSpec.js @@ -178,18 +178,6 @@ defineSuite([ }).toThrow(); }); - it('configures extent', function() { - var extent = new Extent( - 0.0, - 0.0, - CesiumMath.toRadians(10.0), - CesiumMath.toRadians(10.0) - ); - - polygon.configureExtent(extent); - expect(polygon.getPositions()).not.toBeDefined(); - }); - it('gets the default color', function() { expect(polygon.material.uniforms.color).toEqual({ red : 1.0, @@ -228,32 +216,6 @@ defineSuite([ expect(context.readPixels()).not.toEqual([0, 0, 0, 0]); }); - it('renders extent', function() { - // This test fails in Chrome if a breakpoint is set inside this function. Strange. - - var ellipsoid = Ellipsoid.UNIT_SPHERE; - polygon.ellipsoid = ellipsoid; - polygon.granularity = CesiumMath.toRadians(20.0); - polygon.configureExtent(new Extent( - 0.0, - 0.0, - CesiumMath.toRadians(10.0), - CesiumMath.toRadians(10.0) - )); - polygon.material.uniforms.color = { - red : 1.0, - green : 0.0, - blue : 0.0, - alpha : 1.0 - }; - - ClearCommand.ALL.execute(context); - expect(context.readPixels()).toEqual([0, 0, 0, 0]); - - render(context, frameState, polygon); - expect(context.readPixels()).not.toEqual([0, 0, 0, 0]); - }); - it('does not render when show is false', function() { polygon = createPolygon(); polygon.material.uniforms.color = { @@ -312,21 +274,6 @@ defineSuite([ expect(render(context, frameState, polygon)).toEqual(0); }); - it('does not render with empty extent', function() { - var extent = new Extent( - 0.0, - 0.0, - 0.0, - 0.0 - ); - - polygon = new Polygon(); - polygon.ellipsoid = Ellipsoid.UNIT_SPHERE; - polygon.configureExtent(extent); - - expect(render(context, frameState, polygon)).toEqual(0); - }); - it('is picked', function() { polygon = createPolygon(); @@ -399,49 +346,6 @@ defineSuite([ test2DBoundingSphereFromPositions(SceneMode.SCENE2D); }); - it('test 3D bounding sphere from extent', function() { - var ellipsoid = Ellipsoid.UNIT_SPHERE; - var extent = new Extent( - 0.0, - 0.0, - CesiumMath.toRadians(10.0), - CesiumMath.toRadians(10.0)); - - var polygon = new Polygon(); - polygon.ellipsoid = ellipsoid; - polygon.configureExtent(extent); - - var commandList = []; - polygon.update(context, frameState, commandList); - var boundingVolume = commandList[0].colorList[0].boundingVolume; - expect(boundingVolume).toEqual(BoundingSphere.fromExtent3D(extent, ellipsoid)); - }); - - function test2DBoundingSphereFromExtent(testMode) { - var projection = frameState.scene2D.projection; - var ellipsoid = projection.getEllipsoid(); - var extent = new Extent( - 0.0, - 0.0, - CesiumMath.toRadians(10.0), - CesiumMath.toRadians(10.0)); - - var polygon = new Polygon(); - polygon.ellipsoid = ellipsoid; - polygon.configureExtent(extent); - - var mode = frameState.mode; - frameState.mode = testMode; - var commandList = []; - polygon.update(context, frameState, commandList); - var boundingVolume = commandList[0].colorList[0].boundingVolume; - frameState.mode = mode; - - var sphere = BoundingSphere.fromExtent2D(extent, projection); - sphere.center = new Cartesian3(0.0, sphere.center.x, sphere.center.y); - expect(boundingVolume).toEqualEpsilon(sphere, CesiumMath.EPSILON9); - } - it('test 2D bounding sphere from extent', function() { test2DBoundingSphereFromExtent(SceneMode.COLUMBUS_VIEW); }); From acaf7a3a09eb340e2464a5bbe367ca4b61adf483 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Wed, 22 May 2013 16:37:08 -0400 Subject: [PATCH 065/306] Update doc and tests for extent geometry. --- Source/Core/ExtentGeometry.js | 20 +-- Specs/Core/EllipsoidGeometrySpec.js | 2 +- Specs/Core/ExtentGeometrySpec.js | 224 ++++++++++------------------ Specs/Scene/PolygonSpec.js | 8 - 4 files changed, 85 insertions(+), 169 deletions(-) diff --git a/Source/Core/ExtentGeometry.js b/Source/Core/ExtentGeometry.js index b9da7d09abe4..c16905bc99e5 100644 --- a/Source/Core/ExtentGeometry.js +++ b/Source/Core/ExtentGeometry.js @@ -59,7 +59,7 @@ define([ var binormal = new Cartesian3(); /** - * Creates geometry for a cartographic extent of an ellipsoid centered at the origin. + * Creates geometry for a cartographic extent on an ellipsoid centered at the origin. * * @param {Extent} description.extent A cartographic extent with north, south, east and west properties in radians. * @param {Ellipsoid} [description.ellipsoid=Ellipsoid.WGS84] The ellipsoid on which the extent lies. @@ -74,6 +74,7 @@ define([ * @exception {DeveloperError} description.extent.west must be in the interval [-Pi, Pi]. * @exception {DeveloperError} description.extent.north must be greater than extent.south. * @exception {DeveloperError} description.extent.east must be greater than extent.west. + * @exception {DeveloperError} Rotated extent is invalid. * * @see Extent * @@ -138,17 +139,12 @@ define([ proj.unproject(nw, nwCartographic); latitude = nwCartographic.latitude; longitude = nwCartographic.longitude; - if (!isValidLatLon(latitude, longitude)) { //NW corner - return; - } - if (!isValidLatLon(latitude + (width-1)*granXSin, longitude + (width-1)*granXCos)) { //NE corner - return; - } - if (!isValidLatLon(latitude - granYCos*(height-1), longitude + (height-1)*granYSin)) { //SW corner - return; - } - if (!isValidLatLon(latitude - granYCos*(height-1) + (width-1)*granXSin, longitude + (height-1)*granYSin + (width-1)*granXCos)) { //SE corner - return; + + if (!isValidLatLon(latitude, longitude) || + !isValidLatLon(latitude + (width-1)*granXSin, longitude + (width-1)*granXCos) || + !isValidLatLon(latitude - granYCos*(height-1), longitude + (height-1)*granYSin) || + !isValidLatLon(latitude - granYCos*(height-1) + (width-1)*granXSin, longitude + (height-1)*granYSin + (width-1)*granXCos)) { + throw new DeveloperError('Rotated extent is invalid.'); } } diff --git a/Specs/Core/EllipsoidGeometrySpec.js b/Specs/Core/EllipsoidGeometrySpec.js index 0fe48536acb6..65f9035165c8 100644 --- a/Specs/Core/EllipsoidGeometrySpec.js +++ b/Specs/Core/EllipsoidGeometrySpec.js @@ -70,7 +70,7 @@ defineSuite([ expect(position.magnitude()).toEqualEpsilon(1.0, CesiumMath.EPSILON10); expect(normal).toEqualEpsilon(position.normalize(), CesiumMath.EPSILON10); expect(Cartesian3.dot(Cartesian3.UNIT_Z, tangent)).not.toBeLessThan(0.0); - expect(binormal).toEqualEpsilon(Cartesian3.cross(tangent, normal), CesiumMath.EPSILON10); + expect(binormal).toEqualEpsilon(Cartesian3.cross(normal, tangent), CesiumMath.EPSILON10); } }); diff --git a/Specs/Core/ExtentGeometrySpec.js b/Specs/Core/ExtentGeometrySpec.js index 6c8f4608ee1e..2ed8390b138d 100644 --- a/Specs/Core/ExtentGeometrySpec.js +++ b/Specs/Core/ExtentGeometrySpec.js @@ -1,185 +1,113 @@ /*global defineSuite*/ defineSuite([ 'Core/ExtentGeometry', - 'Core/Extent', - 'Core/Ellipsoid', 'Core/Cartesian3', - 'Core/Math' + 'Core/Ellipsoid', + 'Core/Extent', + 'Core/GeographicProjection', + 'Core/Math', + 'Core/Matrix2', + 'Core/VertexFormat' ], function( ExtentGeometry, - Extent, - Ellipsoid, Cartesian3, - CesiumMath) { + Ellipsoid, + Extent, + GeographicProjection, + CesiumMath, + Matrix2, + VertexFormat) { "use strict"; /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/ - it('compute 0', function() { - var m = ExtentGeometry.compute({ - extent : new Extent(-2.0, -1.0, 0.0, 1.0), + it('computes positions', function() { + var extent = new Extent(-2.0, -1.0, 0.0, 1.0); + var m = new ExtentGeometry({ + vertexFormat : VertexFormat.POSITION_ONLY, + extent : extent, granularity : 1.0 }); - expect(m.attributes.position.values.length).toEqual(9 * 3); - expect(typeof m.attributes.textureCoordinates === 'undefined').toEqual(true); + var positions = m.attributes.position.values; + var length = positions.length; + + expect(positions.length).toEqual(9 * 3); expect(m.indexLists[0].values.length).toEqual(8 * 3); + + var expectedNWCorner = Ellipsoid.WGS84.cartographicToCartesian(extent.getNorthwest()); + var expectedSECorner = Ellipsoid.WGS84.cartographicToCartesian(extent.getSoutheast()); + expect(new Cartesian3(positions[0], positions[1], positions[2])).toEqual(expectedNWCorner); + expect(new Cartesian3(positions[length-3], positions[length-2], positions[length-1])).toEqual(expectedSECorner); }); - it('compute 1', function() { - var m = ExtentGeometry.compute({ + it('computes all attributes', function() { + var m = new ExtentGeometry({ + vertexFormat : VertexFormat.ALL, extent : new Extent(-2.0, -1.0, 0.0, 1.0), - granularity : 1.0, - generateTextureCoordinates : true + granularity : 1.0 }); expect(m.attributes.position.values.length).toEqual(9 * 3); - expect(m.attributes.textureCoordinates.values.length).toEqual(9 * 2); + expect(m.attributes.st.values.length).toEqual(9 * 2); + expect(m.attributes.normal.values.length).toEqual(9 * 3); + expect(m.attributes.tangent.values.length).toEqual(9 * 3); + expect(m.attributes.binormal.values.length).toEqual(9 * 3); expect(m.indexLists[0].values.length).toEqual(8 * 3); }); - it('compute returns undefined if rotation makes extent invalid', function() { - expect(typeof ExtentGeometry.compute({ - extent : new Extent(-CesiumMath.PI, -1.0, 0.0, 1.0), - rotation: CesiumMath.PI_OVER_TWO, - granularity : 1.0, - generateTextureCoordinates : true - }) === 'undefined').toEqual(true); - }); - - it('compute vertices', function() { - var extent = new Extent(-CesiumMath.PI, -CesiumMath.PI_OVER_TWO, CesiumMath.PI, CesiumMath.PI_OVER_TWO); - var description = { - extent: extent, - width: Math.ceil(extent.east - extent.west) + 1, - height: Math.ceil(extent.north - extent.south) + 1, - radiiSquared: Ellipsoid.WGS84.getRadiiSquared(), - relativeToCenter: Cartesian3.ZERO, - surfaceHeight: 0, - vertices: [], - indices: [] - }; - ExtentGeometry.computeVertices(description); - var length = description.vertices.length; - var expectedNWCorner = Ellipsoid.WGS84.cartographicToCartesian(extent.getNorthwest()); - var expectedSECorner = Ellipsoid.WGS84.cartographicToCartesian(extent.getSoutheast()); - expect(new Cartesian3(description.vertices[0], description.vertices[1], description.vertices[2])).toEqual(expectedNWCorner); - expect(new Cartesian3(description.vertices[length-3], description.vertices[length-2], description.vertices[length-1])).toEqual(expectedSECorner); - }); - - it('compute vertices with rotation', function() { + it('compute positions with rotation', function() { var extent = new Extent(-1, -1, 1, 1); - var description = { - extent: extent, - rotation: CesiumMath.PI_OVER_TWO, - width: Math.ceil(extent.east - extent.west) + 1, - height: Math.ceil(extent.north - extent.south) + 1, - radiiSquared: Ellipsoid.WGS84.getRadiiSquared(), - relativeToCenter: Cartesian3.ZERO, - surfaceHeight: 0, - vertices: [], - indices: [] - }; - ExtentGeometry.computeVertices(description); - var length = description.vertices.length; + var angle = CesiumMath.PI_OVER_TWO; + var m = new ExtentGeometry({ + vertexFormat : VertexFormat.POSITIONS_ONLY, + extent: extent, + rotation: angle, + granularity : 1.0 + }); + var positions = m.attributes.position.values; + var length = positions.length; + expect(length).toEqual(9 * 3); - expect(description.indices.length).toEqual(8 * 3); - var unrotatedNWCorner = Ellipsoid.WGS84.cartographicToCartesian(extent.getNorthwest()); - var unrotatedSECorner = Ellipsoid.WGS84.cartographicToCartesian(extent.getSoutheast()); - expect(new Cartesian3(description.vertices[0], description.vertices[1], description.vertices[2])).not.toEqual(unrotatedNWCorner); - expect(new Cartesian3(description.vertices[length-3], description.vertices[length-2], description.vertices[length-1])).not.toEqual(unrotatedSECorner); + expect(m.indexLists[0].values.length).toEqual(8 * 3); + + var unrotatedSECorner = extent.getSoutheast(); + var projection = new GeographicProjection(); + var projectedSECorner = projection.project(unrotatedSECorner); + var rotation = Matrix2.fromRotation(angle); + var rotatedSECornerCartographic = projection.unproject(rotation.multiplyByVector(projectedSECorner)); + var rotatedSECorner = Ellipsoid.WGS84.cartographicToCartesian(rotatedSECornerCartographic); + var actual = new Cartesian3(positions[length-3], positions[length-2], positions[length-1]); + expect(actual).toEqualEpsilon(rotatedSECorner, CesiumMath.EPSILON6); }); it('compute vertices with PI rotation', function() { var extent = new Extent(-1, -1, 1, 1); - var description = { - extent: extent, - rotation: CesiumMath.PI, - width: Math.ceil(extent.east - extent.west) + 1, - height: Math.ceil(extent.north - extent.south) + 1, - radiiSquared: Ellipsoid.WGS84.getRadiiSquared(), - relativeToCenter: Cartesian3.ZERO, - surfaceHeight: 0, - vertices: [], - indices: [] - }; - ExtentGeometry.computeVertices(description); - var length = description.vertices.length; + var m = new ExtentGeometry({ + extent: extent, + rotation: CesiumMath.PI, + granularity : 1.0 + }); + var positions = m.attributes.position.values; + var length = positions.length; + expect(length).toEqual(9 * 3); - expect(description.indices.length).toEqual(8 * 3); + expect(m.indexLists[0].values.length).toEqual(8 * 3); + var unrotatedNWCorner = Ellipsoid.WGS84.cartographicToCartesian(extent.getNorthwest()); var unrotatedSECorner = Ellipsoid.WGS84.cartographicToCartesian(extent.getSoutheast()); - expect(new Cartesian3(description.vertices[0], description.vertices[1], description.vertices[2])).toEqualEpsilon(unrotatedSECorner, CesiumMath.EPSILON8); - expect(new Cartesian3(description.vertices[length-3], description.vertices[length-2], description.vertices[length-1])).toEqualEpsilon(unrotatedNWCorner, CesiumMath.EPSILON8); - }); - - it('compute vertices has empty indices and vertices if rotated extent crosses north pole (NE Corner)', function() { - var extent = new Extent(-CesiumMath.PI_OVER_TWO, 1, CesiumMath.PI_OVER_TWO, CesiumMath.PI_OVER_TWO); - var description = { - extent: extent, - rotation: CesiumMath.PI_OVER_TWO, - width: Math.ceil(extent.east - extent.west) + 1, - height: Math.ceil(extent.north - extent.south) + 1, - radiiSquared: Ellipsoid.WGS84.getRadiiSquared(), - relativeToCenter: Cartesian3.ZERO, - surfaceHeight: 0, - vertices: [], - indices: [] - }; - ExtentGeometry.computeVertices(description); - expect(description.vertices.length).toEqual(0); - expect(description.indices.length).toEqual(0); - }); - it('compute vertices has empty indices and vertices if rotated extent crosses south pole (NW Corner)', function() { - var extent = new Extent(-CesiumMath.PI_OVER_TWO, CesiumMath.PI_OVER_TWO, CesiumMath.PI_OVER_TWO, -1); - var description = { - extent : new Extent(-CesiumMath.PI_OVER_TWO, -CesiumMath.PI_OVER_TWO, CesiumMath.PI_OVER_TWO, -1), - rotation: CesiumMath.PI_OVER_TWO, - width: Math.ceil(extent.east - extent.west) + 1, - height: Math.ceil(extent.north - extent.south) + 1, - radiiSquared: Ellipsoid.WGS84.getRadiiSquared(), - relativeToCenter: Cartesian3.ZERO, - surfaceHeight: 0, - vertices: [], - indices: [] - }; - ExtentGeometry.computeVertices(description); - expect(description.vertices.length).toEqual(0); - expect(description.indices.length).toEqual(0); - }); + var actual = new Cartesian3(positions[0], positions[1], positions[2]); + expect(actual).toEqualEpsilon(unrotatedSECorner, CesiumMath.EPSILON8); - it('compute vertices has empty indices and vertices if rotated extent crosses IDL (SW Corner)', function() { - var extent = new Extent(-CesiumMath.PI, 0, -3, 0.3); - var description = { - extent: extent, - rotation: -CesiumMath.PI_OVER_TWO, - width: Math.ceil(extent.east - extent.west) + 1, - height: Math.ceil(extent.north - extent.south) + 1, - radiiSquared: Ellipsoid.WGS84.getRadiiSquared(), - relativeToCenter: Cartesian3.ZERO, - surfaceHeight: 0, - vertices: [], - indices: [] - }; - ExtentGeometry.computeVertices(description); - expect(description.vertices.length).toEqual(0); - expect(description.indices.length).toEqual(0); + actual = new Cartesian3(positions[length-3], positions[length-2], positions[length-1]); + expect(actual).toEqualEpsilon(unrotatedNWCorner, CesiumMath.EPSILON8); }); - it('compute vertices has empty indices and vertices if rotated extent crosses IDL (SE Corner)', function() { - var extent = new Extent(3, 0, CesiumMath.PI, 0.3); - var description = { - extent: extent, - rotation: 0.1, - width: Math.ceil(extent.east - extent.west) + 1, - height: Math.ceil(extent.north - extent.south) + 1, - radiiSquared: Ellipsoid.WGS84.getRadiiSquared(), - relativeToCenter: Cartesian3.ZERO, - surfaceHeight: 0, - vertices: [], - indices: [] - }; - ExtentGeometry.computeVertices(description); - expect(description.vertices.length).toEqual(0); - expect(description.indices.length).toEqual(0); + it('throws if rotated extent is invalid', function() { + expect(function() { + return new ExtentGeometry({ + extent: new Extent(-CesiumMath.PI_OVER_TWO, 1, CesiumMath.PI_OVER_TWO, CesiumMath.PI_OVER_TWO), + rotation: CesiumMath.PI_OVER_TWO + }); + }).toThrow(); }); }); diff --git a/Specs/Scene/PolygonSpec.js b/Specs/Scene/PolygonSpec.js index d1306a5c202a..58b8fd02e5f9 100644 --- a/Specs/Scene/PolygonSpec.js +++ b/Specs/Scene/PolygonSpec.js @@ -346,14 +346,6 @@ defineSuite([ test2DBoundingSphereFromPositions(SceneMode.SCENE2D); }); - it('test 2D bounding sphere from extent', function() { - test2DBoundingSphereFromExtent(SceneMode.COLUMBUS_VIEW); - }); - - it('test 2D bounding sphere from extent', function() { - test2DBoundingSphereFromExtent(SceneMode.SCENE2D); - }); - it('isDestroyed', function() { var p = new Polygon(); expect(p.isDestroyed()).toEqual(false); From 5bc1c21f7662f0b7edeedace5292caca0692cc9b Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Wed, 22 May 2013 17:02:47 -0400 Subject: [PATCH 066/306] Compute bounding sphere of an extent at a height above the surface. --- Source/Core/BoundingSphere.js | 18 +++++++++++++++++- Source/Core/Extent.js | 19 ++++++++++++++++++- Source/Core/ExtentGeometry.js | 2 +- 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/Source/Core/BoundingSphere.js b/Source/Core/BoundingSphere.js index abac452e7466..d9a363fc2596 100644 --- a/Source/Core/BoundingSphere.js +++ b/Source/Core/BoundingSphere.js @@ -291,11 +291,27 @@ define([ * @return {BoundingSphere} The modified result parameter or a new BoundingSphere instance if none was provided. */ BoundingSphere.fromExtent3D = function(extent, ellipsoid, result) { + return BoundingSphere.fromExtentWithHeight3D(extent, ellipsoid, 0.0, result); + }; + + /** + * Computes a bounding sphere from an extent at a given height in 3D. The bounding sphere is created using a subsample of points + * above the ellipsoid and contained in the extent. It may not be accurate for all extents on all types of ellipsoids. + * @memberof BoundingSphere + * + * @param {Extent} extent The valid extent used to create a bounding sphere. + * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid used to determine positions of the extent. + * @param {Number} [surfaceHeight=0.0] The height above the surface of the ellipsoid. + * @param {BoundingSphere} [result] The object onto which to store the result. + * @return {BoundingSphere} The modified result parameter or a new BoundingSphere instance if none was provided. + */ + BoundingSphere.fromExtentWithHeight3D = function(extent, ellipsoid, surfaceHeight, result) { ellipsoid = defaultValue(ellipsoid, Ellipsoid.WGS84); + surfaceHeight = defaultValue(surfaceHeight, 0.0); var positions; if (typeof extent !== 'undefined') { - positions = extent.subsample(ellipsoid, fromExtent3DScratch); + positions = extent.subsampleWithHeight(ellipsoid, surfaceHeight, fromExtent3DScratch); } return BoundingSphere.fromPoints(positions, result); diff --git a/Source/Core/Extent.js b/Source/Core/Extent.js index 853760c5496c..fa2b24025029 100644 --- a/Source/Core/Extent.js +++ b/Source/Core/Extent.js @@ -354,7 +354,6 @@ define([ return this.west >= this.east || this.south >= this.north; }; - var subsampleLlaScratch = new Cartographic(); /** * Samples this Extent so that it includes a list of Cartesian points suitable for passing to * {@link BoundingSphere#fromPoints}. Sampling is necessary to account @@ -365,7 +364,23 @@ define([ * @return {Array} The modified result parameter or a new Array of Cartesians instances if none was provided. */ Extent.prototype.subsample = function(ellipsoid, result) { + return this.subsampleWithHeight(ellipsoid, 0.0, result); + }; + + var subsampleLlaScratch = new Cartographic(); + /** + * Samples this Extent at a height above the ellipsoid so that it includes a list of Cartesian points suitable for passing to + * {@link BoundingSphere#fromPoints}. Sampling is necessary to account + * for extents that cover the poles or cross the equator. + * + * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid to use. + * @param {Number} [surfaceHeight=0.0] The height of the extent above the ellipsoid. + * @param {Array} [result] The array of Cartesians onto which to store the result. + * @return {Array} The modified result parameter or a new Array of Cartesians instances if none was provided. + */ + Extent.prototype.subsampleWithHeight = function(ellipsoid, surfaceHeight, result) { ellipsoid = defaultValue(ellipsoid, Ellipsoid.WGS84); + surfaceHeight = defaultValue(surfaceHeight, 0.0); if (typeof result === 'undefined') { result = []; @@ -378,6 +393,8 @@ define([ var west = this.west; var lla = subsampleLlaScratch; + lla.height = surfaceHeight; + lla.longitude = west; lla.latitude = north; result[length] = ellipsoid.cartographicToCartesian(lla, result[length]); diff --git a/Source/Core/ExtentGeometry.js b/Source/Core/ExtentGeometry.js index c16905bc99e5..7e9277c61fad 100644 --- a/Source/Core/ExtentGeometry.js +++ b/Source/Core/ExtentGeometry.js @@ -313,7 +313,7 @@ define([ * * @type BoundingSphere */ - this.boundingSphere = BoundingSphere.fromExtent3D(extent, ellipsoid); // TODO: surface height + this.boundingSphere = BoundingSphere.fromExtentWithHeight3D(extent, ellipsoid, surfaceHeight); /** * The 4x4 transformation matrix that transforms the geometry from model to world coordinates. From 623d80085602d6d32aff4c6fe0502c5b752c4996 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Wed, 22 May 2013 17:06:19 -0400 Subject: [PATCH 067/306] Update CHANGES.md. --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index fc56081429c4..398f8076a2f3 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -10,6 +10,7 @@ Beta Releases * Replaced tessellators and meshes with geometry. In particular: * Replaced `CubeMapEllipsoidTessellator` with `EllipsoidGeometry`. * Replaced `BoxTessellator` with `BoxGeometry`. + * Replaced `ExtentTessletaor` with `ExtentGeometry`. * Removed `PlaneTessellator`. It was incomplete and not used. * Renamed `MeshFilters` to `GeometryFilters`. * Renamed `MeshFilters.toWireframeInPlace` to `GeometryFilters.toWireframe`. From d5d2d3b0ac2ddff95f312f185bf24c4d5d679922 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Wed, 22 May 2013 19:01:40 -0400 Subject: [PATCH 068/306] Throw exception when extent is not given. Add test. --- Source/Core/ExtentGeometry.js | 4 ++++ Specs/Core/ExtentGeometrySpec.js | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/Source/Core/ExtentGeometry.js b/Source/Core/ExtentGeometry.js index 7e9277c61fad..91ade1a917f1 100644 --- a/Source/Core/ExtentGeometry.js +++ b/Source/Core/ExtentGeometry.js @@ -95,6 +95,10 @@ define([ options = defaultValue(options, defaultValue.EMPTY_OBJECT); var extent = options.extent; + if (typeof extent === 'undefined') { + throw new DeveloperError('extent is required.'); + } + extent.validate(); var granularity = defaultValue(options.granularity, 0.1); diff --git a/Specs/Core/ExtentGeometrySpec.js b/Specs/Core/ExtentGeometrySpec.js index 2ed8390b138d..657af0a0c791 100644 --- a/Specs/Core/ExtentGeometrySpec.js +++ b/Specs/Core/ExtentGeometrySpec.js @@ -101,6 +101,12 @@ defineSuite([ expect(actual).toEqualEpsilon(unrotatedNWCorner, CesiumMath.EPSILON8); }); + it('throws without extent', function() { + expect(function() { + return new ExtentGeometry({}); + }).toThrow(); + }); + it('throws if rotated extent is invalid', function() { expect(function() { return new ExtentGeometry({ From 88099da663829c25b1d4e418e62f21b63444aaf9 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Wed, 22 May 2013 19:17:12 -0400 Subject: [PATCH 069/306] Start adding ellipse and cirlce geometry. --- Source/Core/CircleGeometry.js | 98 ++++++++++++++ Source/Core/EllipseGeometry.js | 185 ++++++++++++++++++++++++++ Source/Core/Shapes.js | 234 --------------------------------- 3 files changed, 283 insertions(+), 234 deletions(-) create mode 100644 Source/Core/CircleGeometry.js create mode 100644 Source/Core/EllipseGeometry.js delete mode 100644 Source/Core/Shapes.js diff --git a/Source/Core/CircleGeometry.js b/Source/Core/CircleGeometry.js new file mode 100644 index 000000000000..90592f5c4c42 --- /dev/null +++ b/Source/Core/CircleGeometry.js @@ -0,0 +1,98 @@ +/*global define*/ +define([ + './clone', + './defaultValue', + './DeveloperError', + './EllipseGeometry' + ], function( + clone, + defaultValue, + DeveloperError, + EllipseGeometry) { + "use strict"; + + /** + * Computes boundary points for a circle on the ellipsoid. + *

    + * The granularity determines the number of points + * in the boundary. A lower granularity results in more points and a more + * exact circle. + *

    + * An outlined circle is rendered by passing the result of this function call to + * {@link Polyline#setPositions}. A filled circle is rendered by passing + * the result to {@link Polygon#setPositions}. + * + * @param {Ellipsoid} ellipsoid The ellipsoid the circle will be on. + * @param {Cartesian3} center The circle's center point in the fixed frame. + * @param {Number} radius The radius in meters. + * @param {Number} [granularity] The angular distance between points on the circle. + * + * @exception {DeveloperError} ellipsoid, center, and radius are required. + * @exception {DeveloperError} radius must be greater than zero. + * @exception {DeveloperError} granularity must be greater than zero. + * + * @see Polyline#setPositions + * @see Polygon#setPositions + * + * @example + * // Create a polyline of a circle + * var polyline = new Polyline(); + * polyline.setPositions(Shapes.computeCircleBoundary( + * ellipsoid, ellipsoid.cartographicToCartesian( + * Cartographic.fromDegrees(-75.59777, 40.03883, 0.0)), 100000.0)); + */ + var CircleGeometry = function(options) { + options = defaultValue(options, defaultValue.EMPTY_OBJECT); + + var radius = defaultValue(options.radius, 1.0); + if (radius <= 0.0) { + throw new DeveloperError('radius must be greater than zero.'); + } + + var ellipseGeometryOptions = clone(options); + ellipseGeometryOptions.semiMajorAxis = radius; + ellipseGeometryOptions.semiMinorAxis = radius; + var ellipseGeometry = new EllipseGeometry(ellipseGeometryOptions); + + /** + * An object containing {@link GeometryAttribute} properties named after each of the + * true values of the {@link VertexFormat} option. + * + * @type Object + */ + this.attributes = ellipseGeometry.attributes; + + /** + * An array of {@link GeometryIndices} defining primitives. + * + * @type Array + */ + this.indexLists = ellipseGeometry.indexLists; + + /** + * A tight-fitting bounding sphere that encloses the vertices of the geometry. + * + * @type BoundingSphere + */ + this.boundingSphere = ellipseGeometry.boundingSphere; + + /** + * The 4x4 transformation matrix that transforms the geometry from model to world coordinates. + * When this is the identity matrix, the geometry is drawn in world coordinates, i.e., Earth's WGS84 coordinates. + * Local reference frames can be used by providing a different transformation matrix, like that returned + * by {@link Transforms.eastNorthUpToFixedFrame}. + * + * @type Matrix4 + * + * @see Transforms.eastNorthUpToFixedFrame + */ + //this.modelMatrix = ellipseGeometry.modelMatrix; + + /** + * DOC_TBA + */ + this.pickData = ellipseGeometry.pickData; + }; + + return CircleGeometry; +}); \ No newline at end of file diff --git a/Source/Core/EllipseGeometry.js b/Source/Core/EllipseGeometry.js new file mode 100644 index 000000000000..474b701aca2d --- /dev/null +++ b/Source/Core/EllipseGeometry.js @@ -0,0 +1,185 @@ +/*global define*/ +define([ + './defaultValue', + './DeveloperError', + './Ellipsoid', + './Math', + './Cartesian2', + './Cartesian3', + './Quaternion', + './Matrix3' + ], function( + defaultValue, + DeveloperError, + Ellipsoid, + CesiumMath, + Cartesian2, + Cartesian3, + Quaternion, + Matrix3) { + "use strict"; + + function computeEllipseQuadrant(cb, cbRadius, aSqr, bSqr, ab, ecc, mag, unitPos, eastVec, northVec, bearing, + thetaPts, thetaPtsIndex, offset, clockDir, ellipsePts, ellipsePtsIndex, numPts) { + var angle; + var theta; + var radius; + var azimuth; + var temp; + var temp2; + var rotAxis; + var tempVec; + + for (var i = 0; i < numPts; i++, thetaPtsIndex += clockDir, ++ellipsePtsIndex) { + theta = (clockDir > 0) ? (thetaPts[thetaPtsIndex] + offset) : (offset - thetaPts[thetaPtsIndex]); + + azimuth = theta + bearing; + + temp = -Math.cos(azimuth); + + rotAxis = eastVec.multiplyByScalar(temp); + + temp = Math.sin(azimuth); + tempVec = northVec.multiplyByScalar(temp); + + rotAxis = rotAxis.add(tempVec); + + temp = Math.cos(theta); + temp = temp * temp; + + temp2 = Math.sin(theta); + temp2 = temp2 * temp2; + + radius = ab / Math.sqrt(bSqr * temp + aSqr * temp2); + angle = radius / cbRadius; + + // Create the quaternion to rotate the position vector to the boundary of the ellipse. + temp = Math.sin(angle / 2.0); + + var unitQuat = (new Quaternion(rotAxis.x * temp, rotAxis.y * temp, rotAxis.z * temp, Math.cos(angle / 2.0))).normalize(); + var rotMtx = Matrix3.fromQuaternion(unitQuat); + + var tmpEllipsePts = rotMtx.multiplyByVector(unitPos); + var unitCart = tmpEllipsePts.normalize(); + tmpEllipsePts = unitCart.multiplyByScalar(mag); + ellipsePts[ellipsePtsIndex] = tmpEllipsePts; + } + } + + /** + * Computes boundary points for an ellipse on the ellipsoid. + *

    + * The granularity determines the number of points + * in the boundary. A lower granularity results in more points and a more + * exact circle. + *

    + * An outlined ellipse is rendered by passing the result of this function call to + * {@link Polyline#setPositions}. A filled ellipse is rendered by passing + * the result to {@link Polygon#setPositions}. + * + * @param {Ellipsoid} ellipsoid The ellipsoid the ellipse will be on. + * @param {Cartesian3} center The ellipse's center point in the fixed frame. + * @param {Number} semiMajorAxis The length of the ellipse's semi-major axis in meters. + * @param {Number} semiMinorAxis The length of the ellipse's semi-minor axis in meters. + * @param {Number} [bearing] The angle from north (clockwise) in radians. The default is zero. + * @param {Number} [granularity] The angular distance between points on the circle. + * + * @exception {DeveloperError} ellipsoid, center, semiMajorAxis, and semiMinorAxis are required. + * @exception {DeveloperError} Semi-major and semi-minor axes must be greater than zero. + * @exception {DeveloperError} granularity must be greater than zero. + * + * @see Polyline#setPositions + * @see Polygon#setPositions + * + * @return The set of points that form the ellipse's boundary. + * + * @example + * // Create a filled ellipse. + * var polygon = new Polygon(); + * polygon.setPositions(Shapes.computeEllipseBoundary( + * ellipsoid, ellipsoid.cartographicToCartesian( + * Cartographic.fromDegrees(-75.59777, 40.03883)), 500000.0, 300000.0, Math.toRadians(60))); + */ + var EllipseGeometry = function(options) { + options = defaultValue(options, defaultValue.EMPTY_OBJECT); + var center = options.center; + + var ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84); + var semiMajorAxis = defaultValue(options.semiMajorAxis, 1.0); + var semiMinorAxis = defaultValue(options.semiMinorAxis, 1.0); + var bearing = defaultValue(options.bearing, 0.0); + var granularity = defaultValue(options.granularity, 0.02); + + if (typeof center === 'undefined') { + throw new DeveloperError('center is required.'); + } + + if (semiMajorAxis <= 0.0 || semiMinorAxis <= 0.0) { + throw new DeveloperError('Semi-major and semi-minor axes must be greater than zero.'); + } + + if (granularity <= 0.0) { + throw new DeveloperError('granularity must be greater than zero.'); + } + + if (semiMajorAxis < semiMinorAxis) { + var t = semiMajorAxis; + semiMajorAxis = semiMinorAxis; + semiMinorAxis = t; + } + + var MAX_ANOMALY_LIMIT = 2.31; + + var aSqr = semiMajorAxis * semiMajorAxis; + var bSqr = semiMinorAxis * semiMinorAxis; + var ab = semiMajorAxis * semiMinorAxis; + + var value = 1.0 - (bSqr / aSqr); + var ecc = Math.sqrt(value); + + var surfPos = Cartesian3.clone(center); + var mag = surfPos.magnitude(); + + var tempVec = new Cartesian3(0.0, 0.0, 1); + var temp = 1.0 / mag; + + var unitPos = surfPos.multiplyByScalar(temp); + var eastVec = tempVec.cross(surfPos).normalize(); + var northVec = unitPos.cross(eastVec); + + var numQuadrantPts = 1 + Math.ceil(CesiumMath.PI_OVER_TWO / granularity); + var deltaTheta = MAX_ANOMALY_LIMIT / (numQuadrantPts - 1); + var thetaPts = []; + var thetaPtsIndex = 0; + + var sampleTheta = 0.0; + for (var i = 0; i < numQuadrantPts; i++, sampleTheta += deltaTheta, ++thetaPtsIndex) { + thetaPts[thetaPtsIndex] = sampleTheta - ecc * Math.sin(sampleTheta); + if (thetaPts[thetaPtsIndex] >= CesiumMath.PI_OVER_TWO) { + thetaPts[thetaPtsIndex] = CesiumMath.PI_OVER_TWO; + numQuadrantPts = i + 1; + break; + } + } + + var ellipsePts = []; + + computeEllipseQuadrant(ellipsoid, surfPos.magnitude(), aSqr, bSqr, ab, ecc, mag, unitPos, eastVec, northVec, bearing, + thetaPts, 0.0, 0.0, 1, ellipsePts, 0, numQuadrantPts - 1); + + computeEllipseQuadrant(ellipsoid, surfPos.magnitude(), aSqr, bSqr, ab, ecc, mag, unitPos, eastVec, northVec, bearing, + thetaPts, numQuadrantPts - 1, Math.PI, -1, ellipsePts, numQuadrantPts - 1, numQuadrantPts - 1); + + computeEllipseQuadrant(ellipsoid, surfPos.magnitude(), aSqr, bSqr, ab, ecc, mag, unitPos, eastVec, northVec, bearing, + thetaPts, 0.0, Math.PI, 1, ellipsePts, (2 * numQuadrantPts) - 2, numQuadrantPts - 1); + + computeEllipseQuadrant(ellipsoid, surfPos.magnitude(), aSqr, bSqr, ab, ecc, mag, unitPos, eastVec, northVec, bearing, + thetaPts, numQuadrantPts - 1, CesiumMath.TWO_PI, -1, ellipsePts, (3 * numQuadrantPts) - 3, numQuadrantPts); + + ellipsePts.push(ellipsePts[0].clone()); // Duplicates first and last point for polyline + + return ellipsePts; + }; + + return EllipseGeometry; +}); \ No newline at end of file diff --git a/Source/Core/Shapes.js b/Source/Core/Shapes.js deleted file mode 100644 index bdb8393a7026..000000000000 --- a/Source/Core/Shapes.js +++ /dev/null @@ -1,234 +0,0 @@ -/*global define*/ -define([ - './defaultValue', - './DeveloperError', - './Math', - './Cartesian2', - './Cartesian3', - './Quaternion', - './Matrix3' - ], function( - defaultValue, - DeveloperError, - CesiumMath, - Cartesian2, - Cartesian3, - Quaternion, - Matrix3) { - "use strict"; - - function _computeEllipseQuadrant(cb, cbRadius, aSqr, bSqr, ab, ecc, mag, unitPos, eastVec, northVec, bearing, - thetaPts, thetaPtsIndex, offset, clockDir, ellipsePts, ellipsePtsIndex, numPts) { - var angle; - var theta; - var radius; - var azimuth; - var temp; - var temp2; - var rotAxis; - var tempVec; - - for (var i = 0; i < numPts; i++, thetaPtsIndex += clockDir, ++ellipsePtsIndex) { - theta = (clockDir > 0) ? (thetaPts[thetaPtsIndex] + offset) : (offset - thetaPts[thetaPtsIndex]); - - azimuth = theta + bearing; - - temp = -Math.cos(azimuth); - - rotAxis = eastVec.multiplyByScalar(temp); - - temp = Math.sin(azimuth); - tempVec = northVec.multiplyByScalar(temp); - - rotAxis = rotAxis.add(tempVec); - - temp = Math.cos(theta); - temp = temp * temp; - - temp2 = Math.sin(theta); - temp2 = temp2 * temp2; - - radius = ab / Math.sqrt(bSqr * temp + aSqr * temp2); - angle = radius / cbRadius; - - // Create the quaternion to rotate the position vector to the boundary of the ellipse. - temp = Math.sin(angle / 2.0); - - var unitQuat = (new Quaternion(rotAxis.x * temp, rotAxis.y * temp, rotAxis.z * temp, Math.cos(angle / 2.0))).normalize(); - var rotMtx = Matrix3.fromQuaternion(unitQuat); - - var tmpEllipsePts = rotMtx.multiplyByVector(unitPos); - var unitCart = tmpEllipsePts.normalize(); - tmpEllipsePts = unitCart.multiplyByScalar(mag); - ellipsePts[ellipsePtsIndex] = tmpEllipsePts; - } - } - - /** - * Functions to compute the boundary positions for shapes, such as circles, - * drawn on the ellipsoid. - * - * @exports Shapes - * - * @demo Cesium Sandcastle Circles and Ellipses Demo - */ - var Shapes = { - /** - * Computes boundary points for a circle on the ellipsoid. - *

    - * The granularity determines the number of points - * in the boundary. A lower granularity results in more points and a more - * exact circle. - *

    - * An outlined circle is rendered by passing the result of this function call to - * {@link Polyline#setPositions}. A filled circle is rendered by passing - * the result to {@link Polygon#setPositions}. - * - * @param {Ellipsoid} ellipsoid The ellipsoid the circle will be on. - * @param {Cartesian3} center The circle's center point in the fixed frame. - * @param {Number} radius The radius in meters. - * @param {Number} [granularity] The angular distance between points on the circle. - * - * @exception {DeveloperError} ellipsoid, center, and radius are required. - * @exception {DeveloperError} radius must be greater than zero. - * @exception {DeveloperError} granularity must be greater than zero. - * - * @see Polyline#setPositions - * @see Polygon#setPositions - * - * @example - * // Create a polyline of a circle - * var polyline = new Polyline(); - * polyline.setPositions(Shapes.computeCircleBoundary( - * ellipsoid, ellipsoid.cartographicToCartesian( - * Cartographic.fromDegrees(-75.59777, 40.03883, 0.0)), 100000.0)); - */ - computeCircleBoundary : function(ellipsoid, center, radius, granularity) { - if (typeof ellipsoid === 'undefined' || typeof center === 'undefined' || typeof radius === 'undefined') { - throw new DeveloperError('ellipsoid, center, and radius are required.'); - } - - if (radius <= 0.0) { - throw new DeveloperError('radius must be greater than zero.'); - } - - granularity = defaultValue(granularity, CesiumMath.toRadians(1.0)); - if (granularity <= 0.0) { - throw new DeveloperError('granularity must be greater than zero.'); - } - - return this.computeEllipseBoundary(ellipsoid, center, radius, radius, 0, granularity); - }, - - /** - * Computes boundary points for an ellipse on the ellipsoid. - *

    - * The granularity determines the number of points - * in the boundary. A lower granularity results in more points and a more - * exact circle. - *

    - * An outlined ellipse is rendered by passing the result of this function call to - * {@link Polyline#setPositions}. A filled ellipse is rendered by passing - * the result to {@link Polygon#setPositions}. - * - * @param {Ellipsoid} ellipsoid The ellipsoid the ellipse will be on. - * @param {Cartesian3} center The ellipse's center point in the fixed frame. - * @param {Number} semiMajorAxis The length of the ellipse's semi-major axis in meters. - * @param {Number} semiMinorAxis The length of the ellipse's semi-minor axis in meters. - * @param {Number} [bearing] The angle from north (clockwise) in radians. The default is zero. - * @param {Number} [granularity] The angular distance between points on the circle. - * - * @exception {DeveloperError} ellipsoid, center, semiMajorAxis, and semiMinorAxis are required. - * @exception {DeveloperError} Semi-major and semi-minor axes must be greater than zero. - * @exception {DeveloperError} granularity must be greater than zero. - * - * @see Polyline#setPositions - * @see Polygon#setPositions - * - * @return The set of points that form the ellipse's boundary. - * - * @example - * // Create a filled ellipse. - * var polygon = new Polygon(); - * polygon.setPositions(Shapes.computeEllipseBoundary( - * ellipsoid, ellipsoid.cartographicToCartesian( - * Cartographic.fromDegrees(-75.59777, 40.03883)), 500000.0, 300000.0, Math.toRadians(60))); - */ - computeEllipseBoundary : function(ellipsoid, center, semiMajorAxis, semiMinorAxis, bearing, granularity) { - if (typeof ellipsoid === 'undefined' || typeof center === 'undefined' || typeof semiMajorAxis === 'undefined' || typeof semiMinorAxis === 'undefined') { - throw new DeveloperError('ellipsoid, center, semiMajorAxis, and semiMinorAxis are required.'); - } - - if (semiMajorAxis <= 0.0 || semiMinorAxis <= 0.0) { - throw new DeveloperError('Semi-major and semi-minor axes must be greater than zero.'); - } - - bearing = bearing || 0.0; - granularity = defaultValue(granularity, CesiumMath.toRadians(1.0)); - - if (granularity <= 0.0) { - throw new DeveloperError('granularity must be greater than zero.'); - } - - if (semiMajorAxis < semiMinorAxis) { - var t = semiMajorAxis; - semiMajorAxis = semiMinorAxis; - semiMinorAxis = t; - } - - var MAX_ANOMALY_LIMIT = 2.31; - - var aSqr = semiMajorAxis * semiMajorAxis; - var bSqr = semiMinorAxis * semiMinorAxis; - var ab = semiMajorAxis * semiMinorAxis; - - var value = 1.0 - (bSqr / aSqr); - var ecc = Math.sqrt(value); - - var surfPos = Cartesian3.clone(center); - var mag = surfPos.magnitude(); - - var tempVec = new Cartesian3(0.0, 0.0, 1); - var temp = 1.0 / mag; - - var unitPos = surfPos.multiplyByScalar(temp); - var eastVec = tempVec.cross(surfPos).normalize(); - var northVec = unitPos.cross(eastVec); - - var numQuadrantPts = 1 + Math.ceil(CesiumMath.PI_OVER_TWO / granularity); - var deltaTheta = MAX_ANOMALY_LIMIT / (numQuadrantPts - 1); - var thetaPts = []; - var thetaPtsIndex = 0; - - var sampleTheta = 0.0; - for (var i = 0; i < numQuadrantPts; i++, sampleTheta += deltaTheta, ++thetaPtsIndex) { - thetaPts[thetaPtsIndex] = sampleTheta - ecc * Math.sin(sampleTheta); - if (thetaPts[thetaPtsIndex] >= CesiumMath.PI_OVER_TWO) { - thetaPts[thetaPtsIndex] = CesiumMath.PI_OVER_TWO; - numQuadrantPts = i + 1; - break; - } - } - - var ellipsePts = []; - - _computeEllipseQuadrant(ellipsoid, surfPos.magnitude(), aSqr, bSqr, ab, ecc, mag, unitPos, eastVec, northVec, bearing, - thetaPts, 0.0, 0.0, 1, ellipsePts, 0, numQuadrantPts - 1); - - _computeEllipseQuadrant(ellipsoid, surfPos.magnitude(), aSqr, bSqr, ab, ecc, mag, unitPos, eastVec, northVec, bearing, - thetaPts, numQuadrantPts - 1, Math.PI, -1, ellipsePts, numQuadrantPts - 1, numQuadrantPts - 1); - - _computeEllipseQuadrant(ellipsoid, surfPos.magnitude(), aSqr, bSqr, ab, ecc, mag, unitPos, eastVec, northVec, bearing, - thetaPts, 0.0, Math.PI, 1, ellipsePts, (2 * numQuadrantPts) - 2, numQuadrantPts - 1); - - _computeEllipseQuadrant(ellipsoid, surfPos.magnitude(), aSqr, bSqr, ab, ecc, mag, unitPos, eastVec, northVec, bearing, - thetaPts, numQuadrantPts - 1, CesiumMath.TWO_PI, -1, ellipsePts, (3 * numQuadrantPts) - 3, numQuadrantPts); - - ellipsePts.push(ellipsePts[0].clone()); // Duplicates first and last point for polyline - - return ellipsePts; - } - }; - - return Shapes; -}); \ No newline at end of file From fd90fc4c96931771dea279ee34992e365a79179c Mon Sep 17 00:00:00 2001 From: Akos Maroy Date: Thu, 23 May 2013 11:32:33 +0200 Subject: [PATCH 070/306] added BaseLayerPicker capability to receive an array of providers and to accept ImageLayers as well as providers --- .../BaseLayerPicker/BaseLayerPicker.js | 32 +++++++++++++++++-- .../BaseLayerPickerViewModel.js | 23 ++++++++++--- 2 files changed, 48 insertions(+), 7 deletions(-) diff --git a/Source/Widgets/BaseLayerPicker/BaseLayerPicker.js b/Source/Widgets/BaseLayerPicker/BaseLayerPicker.js index 5443d2c0eb30..37530d3c11eb 100644 --- a/Source/Widgets/BaseLayerPicker/BaseLayerPicker.js +++ b/Source/Widgets/BaseLayerPicker/BaseLayerPicker.js @@ -42,7 +42,8 @@ define(['./BaseLayerPickerViewModel', * // and in the body, include: <div id="baseLayerPickerContainer"></div> * * //Create the list of available providers we would like the user to select from. - * //This example uses 3, OpenStreetMap, The Black Marble, and a single, non-streaming world image. + * //This example uses 4, OpenStreetMap, The Black Marble, and a single, non-streaming world image, + * //and an array of ImageryLayers with the Bing satellite layer overlayed with the Black Marble layer * var providerViewModels = []; * providerViewModels.push(ImageryProviderViewModel.fromConstants({ * name : 'Open\u00adStreet\u00adMap', @@ -81,6 +82,33 @@ define(['./BaseLayerPickerViewModel', * } * })); * + * providerViewModels.push(ImageryProviderViewModel.fromConstants({ + * name : 'Bing areal with black marble overlay', + * iconUrl : require.toUrl('../Images/ImageryProviders/blackMarble.png'), + * tooltip : 'Bing Areal imagery with the lights of cities and villages trace the outlines of civilization in this global view of the \ +Earth at night as seen by NASA/NOAA\'s Suomi NPP satellite.', + * creationFunction : function() { + * var bing = new BingMapsImageryProvider({ + * url : 'http://dev.virtualearth.net', + * mapStyle : BingMapsStyle.AERIAL, + * proxy : proxyIfNeeded + * }); + * + * var black = new TileMapServiceImageryProvider({ + * url : 'http://cesium.agi.com/blackmarble', + * maximumLevel : 8, + * credit : 'Black Marble imagery courtesy NASA Earth Observatory', + * proxy : proxyIfNeeded, + * }); + * + * var bingLayer = new ImageryLayer(bing); + * var blackLayer = new ImageryLayer(black); + * blackLayer.alpha = 0.4; + * + * return [ bingLayer, blackLayer ]; + * } + * })); + * * //Finally, create the actual widget using our view models. * var layers = centralBody.getImageryLayers(); * var baseLayerPicker = new BaseLayerPicker('baseLayerPickerContainer', layers, providerViewModels); @@ -186,4 +214,4 @@ define(['./BaseLayerPickerViewModel', }; return BaseLayerPicker; -}); \ No newline at end of file +}); diff --git a/Source/Widgets/BaseLayerPicker/BaseLayerPickerViewModel.js b/Source/Widgets/BaseLayerPicker/BaseLayerPickerViewModel.js index ca289838d3b6..d6d6be441195 100644 --- a/Source/Widgets/BaseLayerPicker/BaseLayerPickerViewModel.js +++ b/Source/Widgets/BaseLayerPicker/BaseLayerPickerViewModel.js @@ -1,11 +1,15 @@ /*global define*/ define(['../../Core/DeveloperError', '../../Scene/SceneMode', + '../../Scene/ImageryLayer', + '../../Scene/ImageryProvider', '../createCommand', '../../ThirdParty/knockout' ], function( DeveloperError, SceneMode, + ImageryLayer, + ImageryProvider, createCommand, knockout) { "use strict"; @@ -90,12 +94,21 @@ define(['../../Core/DeveloperError', return selectedViewModel(); }, write : function(value) { - if (imageryLayers.getLength() > 0) { + while (imageryLayers.getLength() > 0) { imageryLayers.remove(imageryLayers.get(0)); } - var newLayer = value.creationCommand(); - if (typeof newLayer !== 'undefined') { - imageryLayers.addImageryProvider(newLayer, 0); + var newLayers = value.creationCommand(); + if (typeof newLayers !== 'undefined') { + if (!(newLayers instanceof Array)) { + newLayers = [ newLayers ]; + } + for (var i = 0; i < newLayers.length; ++i) { + if (newLayers[i] instanceof ImageryLayer) { + imageryLayers.add(newLayers[i], i); + } else { + imageryLayers.addImageryProvider(newLayers[i], i); + } + } } selectedViewModel(value); dropDownVisible(false); @@ -104,4 +117,4 @@ define(['../../Core/DeveloperError', }; return BaseLayerPickerViewModel; -}); \ No newline at end of file +}); From 3b665c367e1b3cb4795d58403fd2050d688909e9 Mon Sep 17 00:00:00 2001 From: Akos Maroy Date: Thu, 23 May 2013 13:17:49 +0200 Subject: [PATCH 071/306] added destroy function to Timeline --- Source/Widgets/Timeline/Timeline.js | 83 +++++++++++++++++++---------- 1 file changed, 54 insertions(+), 29 deletions(-) diff --git a/Source/Widgets/Timeline/Timeline.js b/Source/Widgets/Timeline/Timeline.js index 6c573eee286b..9f11066743a3 100644 --- a/Source/Widgets/Timeline/Timeline.js +++ b/Source/Widgets/Timeline/Timeline.js @@ -5,14 +5,16 @@ define([ '../../Core/DeveloperError', '../../Core/Clock', '../../Core/ClockRange', - '../../Core/JulianDate' + '../../Core/JulianDate', + '../../Core/destroyObject' ], function ( TimelineTrack, TimelineHighlightRange, DeveloperError, Clock, ClockRange, - JulianDate) { + JulianDate, + destroyObject) { "use strict"; var timelineWheelDelta = 1e12; @@ -129,37 +131,33 @@ define([ this.zoomTo(clock.startTime, clock.stopTime); - this._timeBarEle.addEventListener('mousedown', function(e) { - widget._handleMouseDown(e); - }, false); - document.addEventListener('mouseup', function(e) { - widget._handleMouseUp(e); - }, false); - document.addEventListener('mousemove', function(e) { - widget._handleMouseMove(e); - }, false); - this._timeBarEle.addEventListener('DOMMouseScroll', function(e) { - widget._handleMouseWheel(e); - }, false); // Mozilla mouse wheel - this._timeBarEle.addEventListener('mousewheel', function(e) { - widget._handleMouseWheel(e); - }, false); - this._timeBarEle.addEventListener('touchstart', function(e) { - widget._handleTouchStart(e); - }, false); - document.addEventListener('touchmove', function(e) { - widget._handleTouchMove(e); - }, false); - document.addEventListener('touchend', function(e) { - widget._handleTouchEnd(e); - }, false); + this.onmousedown = function(e) { widget._handleMouseDown(e); }; + this._timeBarEle.addEventListener('mousedown', this.onmousedown, false); + + this.onmousemove = function(e) { widget._handleMouseMove(e); }; + this._timeBarEle.addEventListener('mousemove', this.onmousemove, false); + + this.onDOMMouseScroll = function(e) { widget._handleMouseWheel(e); }; + this._timeBarEle.addEventListener('DOMMouseScroll', this.onDOMMouseScroll, false); + + this.onmousewheel = function(e) { widget._handleMouseWheel(e); }; + this._timeBarEle.addEventListener('mousewheel', this.onmousewheel, false); + + this.ontouchstart = function(e) { widget._handleTouchStart(e); }; + this._timeBarEle.addEventListener('touchstart', this.ontouchstart, false); + + this.ontouchmove = function(e) { widget._handleTouchMove(e); }; + this._timeBarEle.addEventListener('touchmove', this.ontouchmove, false); + + this.ontouchend = function(e) { widget._handleTouchEnd(e); }; + this._timeBarEle.addEventListener('touchend', this.ontouchend, false); + this.container.oncontextmenu = function() { return false; }; - window.addEventListener('resize', function() { - widget.handleResize(); - }, false); + this.onresize = function() { widget.handleResize(); }; + window.addEventListener('resize', this.onresize); this.addEventListener = function(type, listener, useCapture) { widget.container.addEventListener(type, listener, useCapture); @@ -673,5 +671,32 @@ define([ this._makeTics(); }; + /** + * Destroys the widget. Should be called if permanently + * removing the widget from layout. + * @memberof Timeline + */ + Timeline.prototype.destroy = function() { + var container = this.container; + + this._timeBarEle.removeEventListener('mousedown', this.onmousedown, false); + this._timeBarEle.removeEventListener('mousemove', this.onmousemove, false); + this._timeBarEle.removeEventListener('DOMMouseScroll', this.onDOMMouseScroll, false); + this._timeBarEle.removeEventListener('mousewheel', this.onmousewheel, false); + this._timeBarEle.removeEventListener('touchstart', this.ontouchstart, false); + this._timeBarEle.removeEventListener('touchmove', this.ontouchmove, false); + this._timeBarEle.removeEventListener('touchend', this.ontouchend, false); + window.removeEventListener('resize', this.onresize); + + this._clock.onTick.removeEventListener(this.updateFromClock, this); + + while (container.firstChild) { + container.removeChild(container.firstChild); + } + container.className = container.className.replace('cesium-timeline-main', ''); + + return destroyObject(this); + }; + return Timeline; }); From 05374b78348c90e9599d06c3c13403dab7e28b66 Mon Sep 17 00:00:00 2001 From: hpinkos Date: Thu, 23 May 2013 12:03:04 -0400 Subject: [PATCH 072/306] initial implementation --- Source/Core/GeometryFilters.js | 143 +++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) diff --git a/Source/Core/GeometryFilters.js b/Source/Core/GeometryFilters.js index d6a857853684..b9c2176c3a93 100644 --- a/Source/Core/GeometryFilters.js +++ b/Source/Core/GeometryFilters.js @@ -3,6 +3,7 @@ define([ './defaultValue', './DeveloperError', './Cartesian3', + './Cartesian2', './EncodedCartesian3', './Matrix3', './Matrix4', @@ -18,6 +19,7 @@ define([ defaultValue, DeveloperError, Cartesian3, + Cartesian2, EncodedCartesian3, Matrix3, Matrix4, @@ -988,5 +990,146 @@ define([ return mesh; }; + var w1 = new Cartesian2(); + var w2 = new Cartesian2(); + var w3 = new Cartesian2(); + var u1 = new Cartesian3(); + var u2 = new Cartesian3(); + var u3 = new Cartesian3(); + GeometryFilters.computeTangentAndBinormal = function(mesh) { + if (typeof mesh === 'undefined') { + throw new DeveloperError('mesh is required.'); + } + var attributes = mesh.attributes; + if (typeof attributes === 'undefined' || typeof attributes.position === 'undefined' || + typeof attributes.position.values === 'undefined') { + throw new DeveloperError('mesh.attributes.position.values is required'); + } + var vertices = mesh.attributes.position.values; + if (mesh.attributes.position.componentsPerAttribute !== 3 || vertices.length % 3 !== 0) { + throw new DeveloperError('mesh.attributes.position.values.length must be a multiple of 3'); + } + if (typeof attributes.normal === 'undefined' || + typeof attributes.normal.values === 'undefined') { + throw new DeveloperError('mesh.attributes.normal.values is required'); + } + var normals = mesh.attributes.normal.values; + if (mesh.attributes.normal.componentsPerAttribute !== 3 || normals.length % 3 !== 0) { + throw new DeveloperError('mesh.attributes.normals.values.length must be a multiple of 3'); + } + if (typeof attributes.st === 'undefined' || + typeof attributes.st.values === 'undefined') { + throw new DeveloperError('mesh.attributes.st.values is required'); + } + var st = mesh.attributes.st.values; + if (mesh.attributes.st.componentsPerAttribute !== 2 || st.length % 2 !== 0) { + throw new DeveloperError('mesh.attributes.st.values.length must be a multiple of 3'); + } + + var indexLists = mesh.indexLists; + if (typeof indexLists === 'undefined') { + return mesh; + } + + var length = indexLists.length; + for (var k = 0; k < length; k++) { + var indices = indexLists[k].values; + if (indexLists[k].primitiveType !== PrimitiveType.TRIANGLES || typeof indices === 'undefined' || + indices.length < 2 || indices.length % 3 !== 0) { + continue; + } + + var numVertices = mesh.attributes.position.values.length/3; + var numIndices = indices.length; + var tan1 = new Array(numVertices*2); + for (var i = 0; i < tan1.length; i++) { + tan1[i] = new Cartesian3(); + } + + for (i = 0; i < numIndices; i+=3) { + var i0 = indices[i]; + var i1 = indices[i+1]; + var i2 = indices[i+2]; + var i03 = i0*3; + var i13 = i1*3; + var i23 = i2*3; + var i02 = i0*2; + var i12 = i1*2; + var i22 = i2*2; + + u1.x = vertices[i03]; + u1.y = vertices[i03+1]; + u1.z = vertices[i03+2]; + u2.x = vertices[i13]; + u2.y = vertices[i13+1]; + u2.z = vertices[i13+2]; + u3.x = vertices[i23]; + u3.y = vertices[i23+1]; + u3.z = vertices[i23+2]; + + w1.x = st[i02]; + w1.y = st[i02+1]; + w2.x = st[i12]; + w2.y = st[i12+1]; + w3.x = st[i22]; + w3.y = st[i22+1]; + + var x1 = u2.x - u1.x; + var x2 = u3.x - u1.x; + var y1 = u2.y - u1.y; + var y2 = u3.y - u1.y; + var z1 = u2.z - u1.z; + var z2 = u3.z - u1.z; + + var s1 = w2.x - w1.x; + var s2 = w3.x - w1.x; + var t1 = w2.y - w1.y; + var t2 = w3.y - w1.y; + + var r = 1.0/(s1 * t2 - s2 * t1); + var sdir = new Cartesian3((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r); + + tan1[i0].add(sdir, tan1[i0]); + tan1[i1].add(sdir, tan1[i1]); + tan1[i2].add(sdir, tan1[i2]); + } + + if (typeof mesh.attributes.tangent === 'undefined') { + mesh.attributes.tangent = new GeometryAttribute({ + componentDatatype: ComponentDatatype.FLOAT, + componentsPerAttribute: 3, + values: new Array(numVertices * 3) + }); + } + if (typeof mesh.attributes.binormal === 'undefined') { + mesh.attributes.binormal = new GeometryAttribute({ + componentDatatype: ComponentDatatype.FLOAT, + componentsPerAttribute: 3, + values: new Array(numVertices * 3) + }); + } + for (i = 0; i < numVertices; i++) { + var i3 = i*3; + var i31 = i3+1; + var i32 = i3+2; + + var n = new Cartesian3(normals[i3], normals[i31], normals[i32]); + var t = tan1[i]; + var tr = new Cartesian3(); + var scalar = n.dot(t); + var v = n.multiplyByScalar(scalar); + tr = (t.subtract(v)).normalize(); + mesh.attributes.tangent.values[i3] = tr.x; + mesh.attributes.tangent.values[i31] = tr.y; + mesh.attributes.tangent.values[i32] = tr.z; + tr = n.cross(tr); + mesh.attributes.binormal.values[i3] = tr.x; + mesh.attributes.binormal.values[i31] = tr.y; + mesh.attributes.binormal.values[i32] = tr.z; + } + } + return mesh; + }; + return GeometryFilters; }); From 5b2c149138759e94a06983410e1c2843c0fa8018 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 23 May 2013 19:31:58 -0400 Subject: [PATCH 073/306] Compute positions and indices for half of an ellipse. Re-add Shapes.js until we can decide if its still needed or not. --- Apps/CesiumViewer/CesiumViewer.js | 15 ++ Source/Core/EllipseGeometry.js | 266 ++++++++++++++++++++---------- Source/Core/Shapes.js | 234 ++++++++++++++++++++++++++ 3 files changed, 424 insertions(+), 91 deletions(-) create mode 100644 Source/Core/Shapes.js diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index f81fb7c19f54..a0c14e73b7ab 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -12,6 +12,7 @@ define([ 'Core/Ellipsoid', 'Core/Extent', 'Core/ExtentTessellator', + 'Core/EllipseGeometry', 'Core/EllipsoidGeometry', 'Core/BoxGeometry', 'Core/GeometryFilters', @@ -37,6 +38,7 @@ define([ Ellipsoid, Extent, ExtentTessellator, + EllipseGeometry, EllipsoidGeometry, BoxGeometry, GeometryFilters, @@ -72,6 +74,7 @@ define([ var scene = widget.scene; + /* var mesh = ExtentTessellator.compute({ extent : new Extent( CesiumMath.toRadians(-180.0), @@ -81,6 +84,18 @@ define([ granularity : 0.006 // More than 64K vertices }); mesh.pickData = 'mesh'; + */ + var ellipsoid = Ellipsoid.WGS84; + var mesh = new EllipseGeometry({ + vertexFormat : VertexFormat.POSITION_ONLY, + ellipsoid : ellipsoid, + center : ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-100, 20)), + semiMinorAxis : 500000.0, + semiMajorAxis : 1000000.0, + bearing : 0.0, + //granularity : 0.75, + pickData : 'mesh' + }); var mesh2 = new EllipsoidGeometry({ ellipsoid : new Ellipsoid(500000.0, 500000.0, 1000000.0), diff --git a/Source/Core/EllipseGeometry.js b/Source/Core/EllipseGeometry.js index 474b701aca2d..15e376bef140 100644 --- a/Source/Core/EllipseGeometry.js +++ b/Source/Core/EllipseGeometry.js @@ -1,70 +1,44 @@ /*global define*/ define([ './defaultValue', + './BoundingSphere', + './Cartesian2', + './Cartesian3', + './Cartographic', + './ComponentDatatype', './DeveloperError', './Ellipsoid', + './GeographicProjection', + './GeometryAttribute', + './GeometryIndices', './Math', - './Cartesian2', - './Cartesian3', - './Quaternion', - './Matrix3' + './Matrix2', + './Matrix4', + './PrimitiveType', + './VertexFormat' ], function( defaultValue, + BoundingSphere, + Cartesian2, + Cartesian3, + Cartographic, + ComponentDatatype, DeveloperError, Ellipsoid, + GeographicProjection, + GeometryAttribute, + GeometryIndices, CesiumMath, - Cartesian2, - Cartesian3, - Quaternion, - Matrix3) { + Matrix2, + Matrix4, + PrimitiveType, + VertexFormat) { "use strict"; - function computeEllipseQuadrant(cb, cbRadius, aSqr, bSqr, ab, ecc, mag, unitPos, eastVec, northVec, bearing, - thetaPts, thetaPtsIndex, offset, clockDir, ellipsePts, ellipsePtsIndex, numPts) { - var angle; - var theta; - var radius; - var azimuth; - var temp; - var temp2; - var rotAxis; - var tempVec; - - for (var i = 0; i < numPts; i++, thetaPtsIndex += clockDir, ++ellipsePtsIndex) { - theta = (clockDir > 0) ? (thetaPts[thetaPtsIndex] + offset) : (offset - thetaPts[thetaPtsIndex]); - - azimuth = theta + bearing; - - temp = -Math.cos(azimuth); - - rotAxis = eastVec.multiplyByScalar(temp); - - temp = Math.sin(azimuth); - tempVec = northVec.multiplyByScalar(temp); - - rotAxis = rotAxis.add(tempVec); - - temp = Math.cos(theta); - temp = temp * temp; - - temp2 = Math.sin(theta); - temp2 = temp2 * temp2; - - radius = ab / Math.sqrt(bSqr * temp + aSqr * temp2); - angle = radius / cbRadius; - - // Create the quaternion to rotate the position vector to the boundary of the ellipse. - temp = Math.sin(angle / 2.0); - - var unitQuat = (new Quaternion(rotAxis.x * temp, rotAxis.y * temp, rotAxis.z * temp, Math.cos(angle / 2.0))).normalize(); - var rotMtx = Matrix3.fromQuaternion(unitQuat); - - var tmpEllipsePts = rotMtx.multiplyByVector(unitPos); - var unitCart = tmpEllipsePts.normalize(); - tmpEllipsePts = unitCart.multiplyByScalar(mag); - ellipsePts[ellipsePtsIndex] = tmpEllipsePts; - } - } + var position = new Cartesian3(); + var reflectedPosition = new Cartesian3(); + var interiorPosition = new Cartesian3(); + var scratchCart = new Cartographic(); /** * Computes boundary points for an ellipse on the ellipsoid. @@ -123,62 +97,172 @@ define([ } if (semiMajorAxis < semiMinorAxis) { - var t = semiMajorAxis; + var temp = semiMajorAxis; semiMajorAxis = semiMinorAxis; - semiMinorAxis = t; + semiMinorAxis = temp; } - var MAX_ANOMALY_LIMIT = 2.31; + var vertexFormat = defaultValue(options.vertexFormat, VertexFormat.DEFAULT); + + var numPts = Math.ceil(CesiumMath.PI_OVER_TWO / granularity) + 1; + var deltaTheta = CesiumMath.PI_OVER_TWO / (numPts - 1); + //var size = 2 * numPts * numPts; + var size = numPts * numPts; + + var reachedPiOverTwo = false; + if (deltaTheta * (numPts - 1) > CesiumMath.PI_OVER_TWO) { + size -= 2 * numPts - 1; + reachedPiOverTwo = true; + } - var aSqr = semiMajorAxis * semiMajorAxis; - var bSqr = semiMinorAxis * semiMinorAxis; - var ab = semiMajorAxis * semiMinorAxis; + var i; + var j; + var numInterior; - var value = 1.0 - (bSqr / aSqr); - var ecc = Math.sqrt(value); + var positions = (vertexFormat.position) ? new Array(size * 3) : undefined; + positions[0] = semiMajorAxis; + positions[1] = 0.0; + positions[2] = 0.0; + var positionIndex = 3; - var surfPos = Cartesian3.clone(center); - var mag = surfPos.magnitude(); + for (i = 1; i < numPts; ++i) { + var angle = Math.min(i * deltaTheta, CesiumMath.PI_OVER_TWO); - var tempVec = new Cartesian3(0.0, 0.0, 1); - var temp = 1.0 / mag; + position.x = Math.cos(angle) * semiMajorAxis; + position.y = Math.sin(angle) * semiMinorAxis; - var unitPos = surfPos.multiplyByScalar(temp); - var eastVec = tempVec.cross(surfPos).normalize(); - var northVec = unitPos.cross(eastVec); + reflectedPosition.x = position.x; + reflectedPosition.y = -position.y; - var numQuadrantPts = 1 + Math.ceil(CesiumMath.PI_OVER_TWO / granularity); - var deltaTheta = MAX_ANOMALY_LIMIT / (numQuadrantPts - 1); - var thetaPts = []; - var thetaPtsIndex = 0; + positions[positionIndex++] = position.x; + positions[positionIndex++] = position.y; + positions[positionIndex++] = position.z; - var sampleTheta = 0.0; - for (var i = 0; i < numQuadrantPts; i++, sampleTheta += deltaTheta, ++thetaPtsIndex) { - thetaPts[thetaPtsIndex] = sampleTheta - ecc * Math.sin(sampleTheta); - if (thetaPts[thetaPtsIndex] >= CesiumMath.PI_OVER_TWO) { - thetaPts[thetaPtsIndex] = CesiumMath.PI_OVER_TWO; - numQuadrantPts = i + 1; - break; + numInterior = 2 * i + 1; + for (j = 1; j < numInterior - 1; ++j) { + var t = j / (numInterior - 1); + Cartesian3.lerp(position, reflectedPosition, t, interiorPosition); + positions[positionIndex++] = interiorPosition.x; + positions[positionIndex++] = interiorPosition.y; + positions[positionIndex++] = interiorPosition.z; } + + positions[positionIndex++] = reflectedPosition.x; + positions[positionIndex++] = reflectedPosition.y; + positions[positionIndex++] = reflectedPosition.z; + } + + /* + i = (reachedPiOverTwo) ? positionIndex - 3 * (2 * numPts - 1) - 1: positionIndex - 1; + for (; i > 0; i -= 3) { + positions[positionIndex++] = -positions[i - 2]; + positions[positionIndex++] = positions[i - 1]; + positions[positionIndex++] = positions[i]; + } + */ + + var projection = new GeographicProjection(ellipsoid); + var centerCart = ellipsoid.cartesianToCartographic(center, scratchCart); + var projectedCenter = projection.project(centerCart); + var rotation = Matrix2.fromRotation(bearing); + + var length = positions.length; + for (i = 0; i < length; i += 3) { + Cartesian3.fromArray(positions, i, position); + Matrix2.multiplyByVector(rotation, position, position); + Cartesian2.add(projectedCenter, position, position); + + var unprojected = projection.unproject(position, scratchCart); + ellipsoid.cartographicToCartesian(unprojected, position); + + positions[i] = position.x; + positions[i + 1] = position.y; + positions[i + 2] = position.z; } - var ellipsePts = []; + var attributes = {}; - computeEllipseQuadrant(ellipsoid, surfPos.magnitude(), aSqr, bSqr, ab, ecc, mag, unitPos, eastVec, northVec, bearing, - thetaPts, 0.0, 0.0, 1, ellipsePts, 0, numQuadrantPts - 1); + if (vertexFormat.position) { + attributes.position = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : positions + }); + } - computeEllipseQuadrant(ellipsoid, surfPos.magnitude(), aSqr, bSqr, ab, ecc, mag, unitPos, eastVec, northVec, bearing, - thetaPts, numQuadrantPts - 1, Math.PI, -1, ellipsePts, numQuadrantPts - 1, numQuadrantPts - 1); + var indicesSize = size * 2 * 3; + var indices = new Array(indicesSize); + var indicesIndex = 0; - computeEllipseQuadrant(ellipsoid, surfPos.magnitude(), aSqr, bSqr, ab, ecc, mag, unitPos, eastVec, northVec, bearing, - thetaPts, 0.0, Math.PI, 1, ellipsePts, (2 * numQuadrantPts) - 2, numQuadrantPts - 1); + for (i = 0; i < numPts - 1; ++i) { + positionIndex = i + 1; + positionIndex *= positionIndex; + var prevIndex = i * i; - computeEllipseQuadrant(ellipsoid, surfPos.magnitude(), aSqr, bSqr, ab, ecc, mag, unitPos, eastVec, northVec, bearing, - thetaPts, numQuadrantPts - 1, CesiumMath.TWO_PI, -1, ellipsePts, (3 * numQuadrantPts) - 3, numQuadrantPts); + indices[indicesIndex++] = positionIndex++; + indices[indicesIndex++] = positionIndex; + indices[indicesIndex++] = prevIndex; - ellipsePts.push(ellipsePts[0].clone()); // Duplicates first and last point for polyline + numInterior = 2 * i + 1; + for (j = 0; j < numInterior - 1; ++j) { + indices[indicesIndex++] = prevIndex++; + indices[indicesIndex++] = positionIndex; + indices[indicesIndex++] = prevIndex; + + indices[indicesIndex++] = positionIndex++; + indices[indicesIndex++] = positionIndex; + indices[indicesIndex++] = prevIndex; + } + + indices[indicesIndex++] = positionIndex++; + indices[indicesIndex++] = positionIndex; + indices[indicesIndex++] = prevIndex; + } - return ellipsePts; + /** + * An object containing {@link GeometryAttribute} properties named after each of the + * true values of the {@link VertexFormat} option. + * + * @type Object + */ + this.attributes = attributes; + + /** + * An array of {@link GeometryIndices} defining primitives. + * + * @type Array + */ + this.indexLists = [ + new GeometryIndices({ + primitiveType : PrimitiveType.TRIANGLES, + values : indices + }) + ]; + + /** + * A tight-fitting bounding sphere that encloses the vertices of the geometry. + * + * @type BoundingSphere + */ + this.boundingSphere = new BoundingSphere(center, semiMajorAxis); + + /** + * The 4x4 transformation matrix that transforms the geometry from model to world coordinates. + * When this is the identity matrix, the geometry is drawn in world coordinates, i.e., Earth's WGS84 coordinates. + * Local reference frames can be used by providing a different transformation matrix, like that returned + * by {@link Transforms.eastNorthUpToFixedFrame}. + * + * @type Matrix4 + * + * @see Transforms.eastNorthUpToFixedFrame + */ + //this.modelMatrix = defaultValue(options.modelMatrix, Matrix4.IDENTITY.clone()); + this.modelMatrix = Matrix4.IDENTITY.clone(); + + /** + * DOC_TBA + */ + this.pickData = options.pickData; }; return EllipseGeometry; diff --git a/Source/Core/Shapes.js b/Source/Core/Shapes.js new file mode 100644 index 000000000000..bdb8393a7026 --- /dev/null +++ b/Source/Core/Shapes.js @@ -0,0 +1,234 @@ +/*global define*/ +define([ + './defaultValue', + './DeveloperError', + './Math', + './Cartesian2', + './Cartesian3', + './Quaternion', + './Matrix3' + ], function( + defaultValue, + DeveloperError, + CesiumMath, + Cartesian2, + Cartesian3, + Quaternion, + Matrix3) { + "use strict"; + + function _computeEllipseQuadrant(cb, cbRadius, aSqr, bSqr, ab, ecc, mag, unitPos, eastVec, northVec, bearing, + thetaPts, thetaPtsIndex, offset, clockDir, ellipsePts, ellipsePtsIndex, numPts) { + var angle; + var theta; + var radius; + var azimuth; + var temp; + var temp2; + var rotAxis; + var tempVec; + + for (var i = 0; i < numPts; i++, thetaPtsIndex += clockDir, ++ellipsePtsIndex) { + theta = (clockDir > 0) ? (thetaPts[thetaPtsIndex] + offset) : (offset - thetaPts[thetaPtsIndex]); + + azimuth = theta + bearing; + + temp = -Math.cos(azimuth); + + rotAxis = eastVec.multiplyByScalar(temp); + + temp = Math.sin(azimuth); + tempVec = northVec.multiplyByScalar(temp); + + rotAxis = rotAxis.add(tempVec); + + temp = Math.cos(theta); + temp = temp * temp; + + temp2 = Math.sin(theta); + temp2 = temp2 * temp2; + + radius = ab / Math.sqrt(bSqr * temp + aSqr * temp2); + angle = radius / cbRadius; + + // Create the quaternion to rotate the position vector to the boundary of the ellipse. + temp = Math.sin(angle / 2.0); + + var unitQuat = (new Quaternion(rotAxis.x * temp, rotAxis.y * temp, rotAxis.z * temp, Math.cos(angle / 2.0))).normalize(); + var rotMtx = Matrix3.fromQuaternion(unitQuat); + + var tmpEllipsePts = rotMtx.multiplyByVector(unitPos); + var unitCart = tmpEllipsePts.normalize(); + tmpEllipsePts = unitCart.multiplyByScalar(mag); + ellipsePts[ellipsePtsIndex] = tmpEllipsePts; + } + } + + /** + * Functions to compute the boundary positions for shapes, such as circles, + * drawn on the ellipsoid. + * + * @exports Shapes + * + * @demo Cesium Sandcastle Circles and Ellipses Demo + */ + var Shapes = { + /** + * Computes boundary points for a circle on the ellipsoid. + *

    + * The granularity determines the number of points + * in the boundary. A lower granularity results in more points and a more + * exact circle. + *

    + * An outlined circle is rendered by passing the result of this function call to + * {@link Polyline#setPositions}. A filled circle is rendered by passing + * the result to {@link Polygon#setPositions}. + * + * @param {Ellipsoid} ellipsoid The ellipsoid the circle will be on. + * @param {Cartesian3} center The circle's center point in the fixed frame. + * @param {Number} radius The radius in meters. + * @param {Number} [granularity] The angular distance between points on the circle. + * + * @exception {DeveloperError} ellipsoid, center, and radius are required. + * @exception {DeveloperError} radius must be greater than zero. + * @exception {DeveloperError} granularity must be greater than zero. + * + * @see Polyline#setPositions + * @see Polygon#setPositions + * + * @example + * // Create a polyline of a circle + * var polyline = new Polyline(); + * polyline.setPositions(Shapes.computeCircleBoundary( + * ellipsoid, ellipsoid.cartographicToCartesian( + * Cartographic.fromDegrees(-75.59777, 40.03883, 0.0)), 100000.0)); + */ + computeCircleBoundary : function(ellipsoid, center, radius, granularity) { + if (typeof ellipsoid === 'undefined' || typeof center === 'undefined' || typeof radius === 'undefined') { + throw new DeveloperError('ellipsoid, center, and radius are required.'); + } + + if (radius <= 0.0) { + throw new DeveloperError('radius must be greater than zero.'); + } + + granularity = defaultValue(granularity, CesiumMath.toRadians(1.0)); + if (granularity <= 0.0) { + throw new DeveloperError('granularity must be greater than zero.'); + } + + return this.computeEllipseBoundary(ellipsoid, center, radius, radius, 0, granularity); + }, + + /** + * Computes boundary points for an ellipse on the ellipsoid. + *

    + * The granularity determines the number of points + * in the boundary. A lower granularity results in more points and a more + * exact circle. + *

    + * An outlined ellipse is rendered by passing the result of this function call to + * {@link Polyline#setPositions}. A filled ellipse is rendered by passing + * the result to {@link Polygon#setPositions}. + * + * @param {Ellipsoid} ellipsoid The ellipsoid the ellipse will be on. + * @param {Cartesian3} center The ellipse's center point in the fixed frame. + * @param {Number} semiMajorAxis The length of the ellipse's semi-major axis in meters. + * @param {Number} semiMinorAxis The length of the ellipse's semi-minor axis in meters. + * @param {Number} [bearing] The angle from north (clockwise) in radians. The default is zero. + * @param {Number} [granularity] The angular distance between points on the circle. + * + * @exception {DeveloperError} ellipsoid, center, semiMajorAxis, and semiMinorAxis are required. + * @exception {DeveloperError} Semi-major and semi-minor axes must be greater than zero. + * @exception {DeveloperError} granularity must be greater than zero. + * + * @see Polyline#setPositions + * @see Polygon#setPositions + * + * @return The set of points that form the ellipse's boundary. + * + * @example + * // Create a filled ellipse. + * var polygon = new Polygon(); + * polygon.setPositions(Shapes.computeEllipseBoundary( + * ellipsoid, ellipsoid.cartographicToCartesian( + * Cartographic.fromDegrees(-75.59777, 40.03883)), 500000.0, 300000.0, Math.toRadians(60))); + */ + computeEllipseBoundary : function(ellipsoid, center, semiMajorAxis, semiMinorAxis, bearing, granularity) { + if (typeof ellipsoid === 'undefined' || typeof center === 'undefined' || typeof semiMajorAxis === 'undefined' || typeof semiMinorAxis === 'undefined') { + throw new DeveloperError('ellipsoid, center, semiMajorAxis, and semiMinorAxis are required.'); + } + + if (semiMajorAxis <= 0.0 || semiMinorAxis <= 0.0) { + throw new DeveloperError('Semi-major and semi-minor axes must be greater than zero.'); + } + + bearing = bearing || 0.0; + granularity = defaultValue(granularity, CesiumMath.toRadians(1.0)); + + if (granularity <= 0.0) { + throw new DeveloperError('granularity must be greater than zero.'); + } + + if (semiMajorAxis < semiMinorAxis) { + var t = semiMajorAxis; + semiMajorAxis = semiMinorAxis; + semiMinorAxis = t; + } + + var MAX_ANOMALY_LIMIT = 2.31; + + var aSqr = semiMajorAxis * semiMajorAxis; + var bSqr = semiMinorAxis * semiMinorAxis; + var ab = semiMajorAxis * semiMinorAxis; + + var value = 1.0 - (bSqr / aSqr); + var ecc = Math.sqrt(value); + + var surfPos = Cartesian3.clone(center); + var mag = surfPos.magnitude(); + + var tempVec = new Cartesian3(0.0, 0.0, 1); + var temp = 1.0 / mag; + + var unitPos = surfPos.multiplyByScalar(temp); + var eastVec = tempVec.cross(surfPos).normalize(); + var northVec = unitPos.cross(eastVec); + + var numQuadrantPts = 1 + Math.ceil(CesiumMath.PI_OVER_TWO / granularity); + var deltaTheta = MAX_ANOMALY_LIMIT / (numQuadrantPts - 1); + var thetaPts = []; + var thetaPtsIndex = 0; + + var sampleTheta = 0.0; + for (var i = 0; i < numQuadrantPts; i++, sampleTheta += deltaTheta, ++thetaPtsIndex) { + thetaPts[thetaPtsIndex] = sampleTheta - ecc * Math.sin(sampleTheta); + if (thetaPts[thetaPtsIndex] >= CesiumMath.PI_OVER_TWO) { + thetaPts[thetaPtsIndex] = CesiumMath.PI_OVER_TWO; + numQuadrantPts = i + 1; + break; + } + } + + var ellipsePts = []; + + _computeEllipseQuadrant(ellipsoid, surfPos.magnitude(), aSqr, bSqr, ab, ecc, mag, unitPos, eastVec, northVec, bearing, + thetaPts, 0.0, 0.0, 1, ellipsePts, 0, numQuadrantPts - 1); + + _computeEllipseQuadrant(ellipsoid, surfPos.magnitude(), aSqr, bSqr, ab, ecc, mag, unitPos, eastVec, northVec, bearing, + thetaPts, numQuadrantPts - 1, Math.PI, -1, ellipsePts, numQuadrantPts - 1, numQuadrantPts - 1); + + _computeEllipseQuadrant(ellipsoid, surfPos.magnitude(), aSqr, bSqr, ab, ecc, mag, unitPos, eastVec, northVec, bearing, + thetaPts, 0.0, Math.PI, 1, ellipsePts, (2 * numQuadrantPts) - 2, numQuadrantPts - 1); + + _computeEllipseQuadrant(ellipsoid, surfPos.magnitude(), aSqr, bSqr, ab, ecc, mag, unitPos, eastVec, northVec, bearing, + thetaPts, numQuadrantPts - 1, CesiumMath.TWO_PI, -1, ellipsePts, (3 * numQuadrantPts) - 3, numQuadrantPts); + + ellipsePts.push(ellipsePts[0].clone()); // Duplicates first and last point for polyline + + return ellipsePts; + } + }; + + return Shapes; +}); \ No newline at end of file From 172591273909c3da982c88346466b954713cbbfb Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 23 May 2013 21:10:30 -0400 Subject: [PATCH 074/306] Start adding positions on ellipse reflected over y axis. (current indices are incorrect). --- Apps/CesiumViewer/CesiumViewer.js | 2 +- Source/Core/EllipseGeometry.js | 82 ++++++++++++++++++++++++++----- 2 files changed, 71 insertions(+), 13 deletions(-) diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index a0c14e73b7ab..92519fef499f 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -93,7 +93,7 @@ define([ semiMinorAxis : 500000.0, semiMajorAxis : 1000000.0, bearing : 0.0, - //granularity : 0.75, + granularity : 0.75, pickData : 'mesh' }); diff --git a/Source/Core/EllipseGeometry.js b/Source/Core/EllipseGeometry.js index 15e376bef140..dc48113a7b63 100644 --- a/Source/Core/EllipseGeometry.js +++ b/Source/Core/EllipseGeometry.js @@ -106,8 +106,7 @@ define([ var numPts = Math.ceil(CesiumMath.PI_OVER_TWO / granularity) + 1; var deltaTheta = CesiumMath.PI_OVER_TWO / (numPts - 1); - //var size = 2 * numPts * numPts; - var size = numPts * numPts; + var size = 2 * numPts * numPts; var reachedPiOverTwo = false; if (deltaTheta * (numPts - 1) > CesiumMath.PI_OVER_TWO) { @@ -152,14 +151,25 @@ define([ positions[positionIndex++] = reflectedPosition.z; } - /* - i = (reachedPiOverTwo) ? positionIndex - 3 * (2 * numPts - 1) - 1: positionIndex - 1; - for (; i > 0; i -= 3) { - positions[positionIndex++] = -positions[i - 2]; - positions[positionIndex++] = positions[i - 1]; - positions[positionIndex++] = positions[i]; + var reverseIndex; + if (reachedPiOverTwo) { + i = numPts - 1; + reverseIndex = positionIndex - (numPts * 2 - 1) * 3; + } else { + i = numPts; + reverseIndex = positionIndex; + } + + for (; i > 0; --i) { + numInterior = 2 * i - 1; + reverseIndex -= numInterior * 3; + for (j = 0; j < numInterior; ++j) { + var index = reverseIndex + j * 3; + positions[positionIndex++] = -positions[index]; + positions[positionIndex++] = positions[index + 1]; + positions[positionIndex++] = positions[index + 2]; + } } - */ var projection = new GeographicProjection(ellipsoid); var centerCart = ellipsoid.cartesianToCartographic(center, scratchCart); @@ -190,14 +200,17 @@ define([ }); } - var indicesSize = size * 2 * 3; - var indices = new Array(indicesSize); + // TODO: compute correct indices array size + //var indicesSize = size * 2 * 3; + //var indices = new Array(indicesSize); + var indices = []; var indicesIndex = 0; + var prevIndex; for (i = 0; i < numPts - 1; ++i) { positionIndex = i + 1; positionIndex *= positionIndex; - var prevIndex = i * i; + prevIndex = i * i; indices[indicesIndex++] = positionIndex++; indices[indicesIndex++] = positionIndex; @@ -219,6 +232,51 @@ define([ indices[indicesIndex++] = prevIndex; } + if (!reachedPiOverTwo) { + numInterior = numPts * 2 - 1; + prevIndex = numPts - 1; + prevIndex *= prevIndex; + --prevIndex; + for (i = 0; i < numInterior - 1; ++i) { + positionIndex = prevIndex + numInterior + 1; + + indices[indicesIndex++] = prevIndex++; + indices[indicesIndex++] = positionIndex; + indices[indicesIndex++] = prevIndex; + + indices[indicesIndex++] = positionIndex++; + indices[indicesIndex++] = positionIndex; + indices[indicesIndex++] = prevIndex; + } + } + + ++prevIndex; + for (i = numPts - 1; i > 0; --i) { + positionIndex = 2 * (i + 1) - 1; + positionIndex += prevIndex; + + indices[indicesIndex++] = prevIndex++; + indices[indicesIndex++] = positionIndex; + indices[indicesIndex++] = prevIndex; + + numInterior = 2 * (i - 1) + 1; + for (j = 0; j < numInterior - 1; ++j) { + indices[indicesIndex++] = prevIndex++; + indices[indicesIndex++] = positionIndex; + indices[indicesIndex++] = prevIndex; + + indices[indicesIndex++] = positionIndex++; + indices[indicesIndex++] = positionIndex; + indices[indicesIndex++] = prevIndex; + } + + indices[indicesIndex++] = prevIndex++; + indices[indicesIndex++] = positionIndex; + indices[indicesIndex++] = prevIndex; + + prevIndex = positionIndex + 1; + } + /** * An object containing {@link GeometryAttribute} properties named after each of the * true values of the {@link VertexFormat} option. From fbfee01a2dd59ef6f883a37fd69f25e9d0474308 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 23 May 2013 23:32:23 -0400 Subject: [PATCH 075/306] Compute correct indices for the half of the ellipse reflected over the y axis. --- Apps/CesiumViewer/CesiumViewer.js | 1 - Source/Core/EllipseGeometry.js | 17 +++++------------ 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index 92519fef499f..138a8a119c44 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -93,7 +93,6 @@ define([ semiMinorAxis : 500000.0, semiMajorAxis : 1000000.0, bearing : 0.0, - granularity : 0.75, pickData : 'mesh' }); diff --git a/Source/Core/EllipseGeometry.js b/Source/Core/EllipseGeometry.js index dc48113a7b63..a26fc336478c 100644 --- a/Source/Core/EllipseGeometry.js +++ b/Source/Core/EllipseGeometry.js @@ -234,12 +234,9 @@ define([ if (!reachedPiOverTwo) { numInterior = numPts * 2 - 1; - prevIndex = numPts - 1; - prevIndex *= prevIndex; - --prevIndex; + ++positionIndex; + ++prevIndex; for (i = 0; i < numInterior - 1; ++i) { - positionIndex = prevIndex + numInterior + 1; - indices[indicesIndex++] = prevIndex++; indices[indicesIndex++] = positionIndex; indices[indicesIndex++] = prevIndex; @@ -251,10 +248,8 @@ define([ } ++prevIndex; + ++positionIndex; for (i = numPts - 1; i > 0; --i) { - positionIndex = 2 * (i + 1) - 1; - positionIndex += prevIndex; - indices[indicesIndex++] = prevIndex++; indices[indicesIndex++] = positionIndex; indices[indicesIndex++] = prevIndex; @@ -271,10 +266,8 @@ define([ } indices[indicesIndex++] = prevIndex++; - indices[indicesIndex++] = positionIndex; - indices[indicesIndex++] = prevIndex; - - prevIndex = positionIndex + 1; + indices[indicesIndex++] = positionIndex++; + indices[indicesIndex++] = prevIndex++; } /** From b59df7b04621e6876f5f7500176acdb9c7181cf0 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Fri, 24 May 2013 00:46:18 -0400 Subject: [PATCH 076/306] Compute the number of indices up front. --- Source/Core/EllipseGeometry.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/Source/Core/EllipseGeometry.js b/Source/Core/EllipseGeometry.js index a26fc336478c..870954afe8fd 100644 --- a/Source/Core/EllipseGeometry.js +++ b/Source/Core/EllipseGeometry.js @@ -200,10 +200,15 @@ define([ }); } - // TODO: compute correct indices array size - //var indicesSize = size * 2 * 3; - //var indices = new Array(indicesSize); - var indices = []; + var indicesSize = numPts * (numPts - 1.0) / 2.0; + indicesSize *= 4.0; + indicesSize += (numPts - 1.0) * 2.0; + indicesSize *= 2.0 * 3.0; + if (reachedPiOverTwo) { + indicesSize += (((numPts * 2.0 - 1.0) * 2.0) - 2.0) * 3.0; + } + + var indices = new Array(indicesSize); var indicesIndex = 0; var prevIndex; From 0e916570f4ac63e2f941865337e2fc5818e19f28 Mon Sep 17 00:00:00 2001 From: hpinkos Date: Fri, 24 May 2013 13:48:52 -0400 Subject: [PATCH 077/306] working implementation with some tests --- Source/Core/EllipsoidGeometry.js | 4 +- Source/Core/GeometryFilters.js | 11 ++- Specs/Core/GeometryFiltersSpec.js | 126 ++++++++++++++++++++++++------ 3 files changed, 109 insertions(+), 32 deletions(-) diff --git a/Source/Core/EllipsoidGeometry.js b/Source/Core/EllipsoidGeometry.js index d14fe63f1ca5..99455712808b 100644 --- a/Source/Core/EllipsoidGeometry.js +++ b/Source/Core/EllipsoidGeometry.js @@ -262,8 +262,8 @@ define([ for (i = j = 0; i < length; ++i, j += 3) { ellipsoid.geodeticSurfaceNormal(positions[i], normal); - Cartesian3.cross(Cartesian3.UNIT_Z, normal, tangent); - Cartesian3.cross(tangent, normal, binormal); + Cartesian3.cross(Cartesian3.UNIT_Z, normal, tangent).normalize(tangent); + Cartesian3.cross(tangent, normal, binormal).normalize(binormal); if (vertexFormat.normal) { normals[j] = normal.x; diff --git a/Source/Core/GeometryFilters.js b/Source/Core/GeometryFilters.js index b9c2176c3a93..2dd853ce4ee7 100644 --- a/Source/Core/GeometryFilters.js +++ b/Source/Core/GeometryFilters.js @@ -863,7 +863,7 @@ define([ var v0 = new Cartesian3(); var v1 = new Cartesian3(); var v2 = new Cartesian3(); - GeometryFilters.computeNormals = function(mesh) { + GeometryFilters.computeNormal = function(mesh) { if (typeof mesh === 'undefined') { throw new DeveloperError('mesh is required.'); } @@ -1041,7 +1041,7 @@ define([ var numVertices = mesh.attributes.position.values.length/3; var numIndices = indices.length; - var tan1 = new Array(numVertices*2); + var tan1 = new Array(numVertices); for (var i = 0; i < tan1.length; i++) { tan1[i] = new Cartesian3(); } @@ -1114,15 +1114,14 @@ define([ var i32 = i3+2; var n = new Cartesian3(normals[i3], normals[i31], normals[i32]); - var t = tan1[i]; - var tr = new Cartesian3(); + var t = tan1[i].normalize(); var scalar = n.dot(t); var v = n.multiplyByScalar(scalar); - tr = (t.subtract(v)).normalize(); + var tr = (t.subtract(v)).normalize(); mesh.attributes.tangent.values[i3] = tr.x; mesh.attributes.tangent.values[i31] = tr.y; mesh.attributes.tangent.values[i32] = tr.z; - tr = n.cross(tr); + tr = tr.cross(n, tr).normalize(); mesh.attributes.binormal.values[i3] = tr.x; mesh.attributes.binormal.values[i31] = tr.y; mesh.attributes.binormal.values[i32] = tr.z; diff --git a/Specs/Core/GeometryFiltersSpec.js b/Specs/Core/GeometryFiltersSpec.js index 504c3bb690ad..4e96fe413b98 100644 --- a/Specs/Core/GeometryFiltersSpec.js +++ b/Specs/Core/GeometryFiltersSpec.js @@ -11,7 +11,9 @@ defineSuite([ 'Core/GeographicProjection', 'Core/Geometry', 'Core/GeometryAttribute', - 'Core/GeometryIndices' + 'Core/GeometryIndices', + 'Core/VertexFormat', + 'Core/Math' ], function( GeometryFilters, PrimitiveType, @@ -24,7 +26,9 @@ defineSuite([ GeographicProjection, Geometry, GeometryAttribute, - GeometryIndices) { + GeometryIndices, + VertexFormat, + CesiumMath) { "use strict"; /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/ @@ -608,29 +612,29 @@ defineSuite([ }).toThrow(); }); - it('GeometryFilters.computeNormals throws when mesh is undefined', function() { + it('GeometryFilters.computeNormal throws when mesh is undefined', function() { expect(function() { - GeometryFilters.computeNormals(); + GeometryFilters.computeNormal(); }).toThrow(); }); - it('GeometryFilters.computeNormals throws when mesh.attributes is undefined', function() { + it('GeometryFilters.computeNormal throws when mesh.attributes is undefined', function() { expect(function() { - GeometryFilters.computeNormals(new Geometry()); + GeometryFilters.computeNormal(new Geometry()); }).toThrow(); }); - it('GeometryFilters.computeNormals throws when mesh.attributes.position is undefined', function() { + it('GeometryFilters.computeNormal throws when mesh.attributes.position is undefined', function() { expect(function() { - GeometryFilters.computeNormals(new Geometry( { + GeometryFilters.computeNormal(new Geometry( { attributes: {} })); }).toThrow(); }); - it('GeometryFilters.computeNormals throws when mesh.attributes.position.values is undefined', function() { + it('GeometryFilters.computeNormal throws when mesh.attributes.position.values is undefined', function() { expect(function() { - GeometryFilters.computeNormals(new Geometry( { + GeometryFilters.computeNormal(new Geometry( { attributes: { position: {} } @@ -638,9 +642,9 @@ defineSuite([ }).toThrow(); }); - it('GeometryFilters.computeNormals throws when mesh.attributes.position.componentsPerAttribute is not 3', function() { + it('GeometryFilters.computeNormal throws when mesh.attributes.position.componentsPerAttribute is not 3', function() { expect(function() { - GeometryFilters.computeNormals(new Geometry( { + GeometryFilters.computeNormal(new Geometry( { attributes: { position: { values: [3, 2, 1, 1, 2, 4], @@ -651,9 +655,9 @@ defineSuite([ }).toThrow(); }); - it('GeometryFilters.computeNormals throws when mesh.attributes.position.values is not a multiple of 3', function() { + it('GeometryFilters.computeNormal throws when mesh.attributes.position.values is not a multiple of 3', function() { expect(function() { - GeometryFilters.computeNormals(new Geometry( { + GeometryFilters.computeNormal(new Geometry( { attributes: { position: { values: [3, 2, 1, 1, 2, 4, 3], @@ -664,7 +668,7 @@ defineSuite([ }).toThrow(); }); - it('GeometryFilters.computeNormals does not compute normals when mesh.indexLists is undefined', function() { + it('GeometryFilters.computeNormal does not compute normals when mesh.indexLists is undefined', function() { var mesh = new Geometry({ attributes: { position: { @@ -676,12 +680,12 @@ defineSuite([ } }); - mesh = GeometryFilters.computeNormals(mesh); + mesh = GeometryFilters.computeNormal(mesh); expect(typeof mesh.attributes.normal === 'undefined').toEqual(true); }); - it('GeometryFilters.computeNormals does not compute normals when primitive type is not triangle', function() { + it('GeometryFilters.computeNormal does not compute normals when primitive type is not triangle', function() { var mesh = new Geometry({ attributes: { position: { @@ -698,13 +702,13 @@ defineSuite([ }] }); - mesh = GeometryFilters.computeNormals(mesh); + mesh = GeometryFilters.computeNormal(mesh); expect(typeof mesh.attributes.normal === 'undefined').toEqual(true); }); - it('GeometryFilters.computeNormals computes normal for one triangle', function() { + it('GeometryFilters.computeNormal computes normal for one triangle', function() { var mesh = new Geometry({ attributes: { position: { @@ -720,13 +724,13 @@ defineSuite([ }] }); - mesh = GeometryFilters.computeNormals(mesh); + mesh = GeometryFilters.computeNormal(mesh); expect(mesh.attributes.normal.values.length).toEqual(3*3); expect(mesh.attributes.normal.values).toEqual([0, 0, 1, 0, 0, 1, 0, 0, 1]); }); - it('GeometryFilters.computeNormals computes normal for two triangles', function() { + it('GeometryFilters.computeNormal computes normal for two triangles', function() { var mesh = new Geometry({ attributes: { position: { @@ -743,7 +747,7 @@ defineSuite([ }] }); - mesh = GeometryFilters.computeNormals(mesh); + mesh = GeometryFilters.computeNormal(mesh); expect(mesh.attributes.normal.values.length).toEqual(4*3); var a = new Cartesian3(-1, 0, 1).normalize(); @@ -753,7 +757,7 @@ defineSuite([ expect(mesh.attributes.normal.values.slice(9, 12)).toEqual([a.x, a.y, a.z]); }); - it('GeometryFilters.computeNormals computes normal for six triangles', function() { + it('GeometryFilters.computeNormal computes normal for six triangles', function() { var mesh = new Geometry ({ attributes: { position: { @@ -773,7 +777,7 @@ defineSuite([ }] }); - mesh = GeometryFilters.computeNormals(mesh); + mesh = GeometryFilters.computeNormal(mesh); expect(mesh.attributes.normal.values.length).toEqual(7*3); var a = new Cartesian3(-1, -1, -1).normalize(); @@ -788,4 +792,78 @@ defineSuite([ expect(mesh.attributes.normal.values.slice(15,18)).toEqual([a.x, a.y, a.z]); expect(mesh.attributes.normal.values.slice(18,21)).toEqual([0, 0, -1]); }); + + it('GeometryFilters.computeTangentAndBinormal computes tangent and binormal for one triangle', function() { + var mesh = new Geometry({ + attributes: { + position: { + values: [0, 0, 0, + 1, 0, 0, + 0, 1, 0], + componentsPerAttribute: 3 + }, + st: { + values: [0, 0, + 1, 0, + 0, 1], + componentsPerAttribute: 2 + } + }, + indexLists: [{ + primitiveType: PrimitiveType.TRIANGLES, + values: [0, 1, 2] + }] + }); + + mesh = GeometryFilters.computeNormal(mesh); + mesh = GeometryFilters.computeTangentAndBinormal(mesh); + + expect(mesh.attributes.tangent.values).toEqual([1, 0, 0, 1, 0, 0, 1, 0, 0]); + expect(mesh.attributes.binormal.values).toEqual([0, -1, 0, 0, -1, 0, 0, -1, 0]); + }); + + it('GeometryFilters.computeTangentAndBinormal computes tangent and binormal for two triangles', function() { + var mesh = new Geometry({ + attributes: { + position: { + values: [0, 0, 0, + 1, 0, 1, + 1, 1, 1, + 2, 0, 0], + componentsPerAttribute: 3 + }, + st: { + values: [0, 0, + 1, 0, + 1, 1, + 0, 1], + componentsPerAttribute: 2 + } + }, + indexLists: [{ + primitiveType: PrimitiveType.TRIANGLES, + values: [0, 1, 2, 1, 3, 2] + }] + }); + + mesh = GeometryFilters.computeNormal(mesh); + mesh = GeometryFilters.computeTangentAndBinormal(mesh); + expect(mesh.attributes.tangent.values).toEqualEpsilon([0.7071067811865475, 0, 0.7071067811865475, + 0, 1, 0, + 0, 1, 0, + -0.5773502691896258, 0.5773502691896258, 0.5773502691896258], CesiumMath.EPSILON8); + expect(mesh.attributes.binormal.values).toEqualEpsilon([0, -1, 0, + 1, 0, 0, + 1, 0, 0, + 0.4082482904638631, 0.8164965809277261, -0.4082482904638631], CesiumMath.EPSILON8); + }); + + it ('GeometryFilters.computeTangentAndBinormal computes tangent and binormal for an EllipsoidGeometry', function() { + var mesh = new EllipsoidGeometry(); + var expected = new EllipsoidGeometry({vertexFormat: new VertexFormat({tangent: true, binormal: true})}); + + mesh = GeometryFilters.computeTangentAndBinormal(mesh); + expect(mesh.attributes.tangent.values.slice(1000,1200)).toEqualEpsilon(expected.attributes.tangent.values.slice(1000,1200), CesiumMath.EPSILON1); + expect(mesh.attributes.binormal.values.slice(1000,1200)).toEqualEpsilon(expected.attributes.binormal.values.slice(1000,1200), CesiumMath.EPSILON1); + }); }); \ No newline at end of file From a1a8d25af8edf1c1c2a3e483a8ca4ccb58959333 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Fri, 24 May 2013 13:58:39 -0400 Subject: [PATCH 078/306] Add texture coordinates, normals, tangents and binormals to ellipse geometry. --- Source/Core/EllipseGeometry.js | 87 ++++++++++++++++++++++++++++++++-- 1 file changed, 83 insertions(+), 4 deletions(-) diff --git a/Source/Core/EllipseGeometry.js b/Source/Core/EllipseGeometry.js index 870954afe8fd..10b7ad8a6922 100644 --- a/Source/Core/EllipseGeometry.js +++ b/Source/Core/EllipseGeometry.js @@ -39,6 +39,9 @@ define([ var reflectedPosition = new Cartesian3(); var interiorPosition = new Cartesian3(); var scratchCart = new Cartographic(); + var normal = new Cartesian3(); + var tangent = new Cartesian3(); + var binormal = new Cartesian3(); /** * Computes boundary points for an ellipse on the ellipsoid. @@ -118,7 +121,7 @@ define([ var j; var numInterior; - var positions = (vertexFormat.position) ? new Array(size * 3) : undefined; + var positions = new Array(size * 3); positions[0] = semiMajorAxis; positions[1] = 0.0; positions[2] = 0.0; @@ -171,6 +174,13 @@ define([ } } + var textureCoordinates = (vertexFormat.st) ? new Array(size * 2) : undefined; + var normals = (vertexFormat.normal) ? new Array(size * 3) : undefined; + var tangents = (vertexFormat.tangent) ? new Array(size * 3) : undefined; + var binormals = (vertexFormat.binormal) ? new Array(size * 3) : undefined; + + var textureCoordIndex = 0; + var projection = new GeographicProjection(ellipsoid); var centerCart = ellipsoid.cartesianToCartographic(center, scratchCart); var projectedCenter = projection.project(centerCart); @@ -179,15 +189,50 @@ define([ var length = positions.length; for (i = 0; i < length; i += 3) { Cartesian3.fromArray(positions, i, position); + + if (vertexFormat.st) { + textureCoordinates[textureCoordIndex++] = (position.x + semiMajorAxis) / (2.0 * semiMajorAxis); + textureCoordinates[textureCoordIndex++] = (position.y + semiMinorAxis) / (2.0 * semiMinorAxis); + } + Matrix2.multiplyByVector(rotation, position, position); Cartesian2.add(projectedCenter, position, position); var unprojected = projection.unproject(position, scratchCart); ellipsoid.cartographicToCartesian(unprojected, position); - positions[i] = position.x; - positions[i + 1] = position.y; - positions[i + 2] = position.z; + if (vertexFormat.position) { + positions[i] = position.x; + positions[i + 1] = position.y; + positions[i + 2] = position.z; + } + + if (vertexFormat.normal) { + ellipsoid.geodeticSurfaceNormal(position, normal); + + normals[i] = normal.x; + normals[i + 1] = normal.y; + normals[i + 2] = normal.z; + } + + if (vertexFormat.tangent) { + ellipsoid.geodeticSurfaceNormal(position, normal); + Cartesian3.cross(Cartesian3.UNIT_Z, normal, tangent); + + tangents[i] = tangent.x; + tangents[i + 1] = tangent.y; + tangents[i + 2] = tangent.z; + } + + if (vertexFormat.binormal) { + ellipsoid.geodeticSurfaceNormal(position, normal); + Cartesian3.cross(Cartesian3.UNIT_Z, normal, tangent); + Cartesian3.cross(normal, tangent, binormal); + + binormals[i] = binormal.x; + binormals[i + 1] = binormal.y; + binormals[i + 2] = binormal.z; + } } var attributes = {}; @@ -200,6 +245,38 @@ define([ }); } + if (vertexFormat.st) { + attributes.st = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 2, + values : textureCoordinates + }); + } + + if (vertexFormat.normal) { + attributes.normal = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : normals + }); + } + + if (vertexFormat.tangent) { + attributes.tangent = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : tangents + }); + } + + if (vertexFormat.binormal) { + attributes.binormal = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : binormals + }); + } + var indicesSize = numPts * (numPts - 1.0) / 2.0; indicesSize *= 4.0; indicesSize += (numPts - 1.0) * 2.0; @@ -275,6 +352,8 @@ define([ indices[indicesIndex++] = prevIndex++; } + indices.length = indicesIndex; + /** * An object containing {@link GeometryAttribute} properties named after each of the * true values of the {@link VertexFormat} option. From ec6ab9a85b19ac6110a99807958e00734fdb5ba4 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Fri, 24 May 2013 14:16:35 -0400 Subject: [PATCH 079/306] Update geometry doc. --- Source/Core/CircleGeometry.js | 43 +++++++++++++-------------- Source/Core/EllipseGeometry.js | 54 ++++++++++++++++------------------ 2 files changed, 45 insertions(+), 52 deletions(-) diff --git a/Source/Core/CircleGeometry.js b/Source/Core/CircleGeometry.js index 90592f5c4c42..63eed95ebc6d 100644 --- a/Source/Core/CircleGeometry.js +++ b/Source/Core/CircleGeometry.js @@ -12,34 +12,31 @@ define([ "use strict"; /** - * Computes boundary points for a circle on the ellipsoid. - *

    - * The granularity determines the number of points - * in the boundary. A lower granularity results in more points and a more - * exact circle. - *

    - * An outlined circle is rendered by passing the result of this function call to - * {@link Polyline#setPositions}. A filled circle is rendered by passing - * the result to {@link Polygon#setPositions}. + * Computes vertices and indices for a circle on the ellipsoid. * - * @param {Ellipsoid} ellipsoid The ellipsoid the circle will be on. - * @param {Cartesian3} center The circle's center point in the fixed frame. - * @param {Number} radius The radius in meters. - * @param {Number} [granularity] The angular distance between points on the circle. + * @alias EllipseGeometry + * @constructor * - * @exception {DeveloperError} ellipsoid, center, and radius are required. + * @param {Cartesian3} options.center The ellipse's center point in the fixed frame. + * @param {Number} [options.center=1.0] The radius in meters. + * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid the ellipse will be on. + * @param {Number} [options.granularity=0.02] The angular distance between points on the circle. + * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed. + * @param {Matrix4} [options.modelMatrix] The model matrix for this ellipsoid. + * @param {DOC_TBA} [options.pickData] DOC_TBA + * + * @exception {DeveloperError} center is required. * @exception {DeveloperError} radius must be greater than zero. * @exception {DeveloperError} granularity must be greater than zero. * - * @see Polyline#setPositions - * @see Polygon#setPositions - * * @example - * // Create a polyline of a circle - * var polyline = new Polyline(); - * polyline.setPositions(Shapes.computeCircleBoundary( - * ellipsoid, ellipsoid.cartographicToCartesian( - * Cartographic.fromDegrees(-75.59777, 40.03883, 0.0)), 100000.0)); + * // Create a circle. + * var ellipsoid = Ellipsoid.WGS84; + * var circle = new CircleGeometry({ + * ellipsoid : ellipsoid, + * center : ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-75.59777, 40.03883)), + * radius : 100000.0 + * }); */ var CircleGeometry = function(options) { options = defaultValue(options, defaultValue.EMPTY_OBJECT); @@ -86,7 +83,7 @@ define([ * * @see Transforms.eastNorthUpToFixedFrame */ - //this.modelMatrix = ellipseGeometry.modelMatrix; + this.modelMatrix = ellipseGeometry.modelMatrix; /** * DOC_TBA diff --git a/Source/Core/EllipseGeometry.js b/Source/Core/EllipseGeometry.js index 10b7ad8a6922..209ed179cdf5 100644 --- a/Source/Core/EllipseGeometry.js +++ b/Source/Core/EllipseGeometry.js @@ -44,38 +44,35 @@ define([ var binormal = new Cartesian3(); /** - * Computes boundary points for an ellipse on the ellipsoid. - *

    - * The granularity determines the number of points - * in the boundary. A lower granularity results in more points and a more - * exact circle. - *

    - * An outlined ellipse is rendered by passing the result of this function call to - * {@link Polyline#setPositions}. A filled ellipse is rendered by passing - * the result to {@link Polygon#setPositions}. + * Computes vertices and indices for an ellipse on the ellipsoid. * - * @param {Ellipsoid} ellipsoid The ellipsoid the ellipse will be on. - * @param {Cartesian3} center The ellipse's center point in the fixed frame. - * @param {Number} semiMajorAxis The length of the ellipse's semi-major axis in meters. - * @param {Number} semiMinorAxis The length of the ellipse's semi-minor axis in meters. - * @param {Number} [bearing] The angle from north (clockwise) in radians. The default is zero. - * @param {Number} [granularity] The angular distance between points on the circle. + * @alias EllipseGeometry + * @constructor * - * @exception {DeveloperError} ellipsoid, center, semiMajorAxis, and semiMinorAxis are required. - * @exception {DeveloperError} Semi-major and semi-minor axes must be greater than zero. - * @exception {DeveloperError} granularity must be greater than zero. - * - * @see Polyline#setPositions - * @see Polygon#setPositions + * @param {Cartesian3} options.center The ellipse's center point in the fixed frame. + * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid the ellipse will be on. + * @param {Number} [options.semiMajorAxis=1.0] The length of the ellipse's semi-major axis in meters. + * @param {Number} [options.semiMinorAxis=1.0] The length of the ellipse's semi-minor axis in meters. + * @param {Number} [options.bearing=0.0] The angle from north (clockwise) in radians. The default is zero. + * @param {Number} [options.granularity=0.02] The angular distance between points on the circle. + * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed. + * @param {Matrix4} [options.modelMatrix] The model matrix for this ellipsoid. + * @param {DOC_TBA} [options.pickData] DOC_TBA * - * @return The set of points that form the ellipse's boundary. + * @exception {DeveloperError} center is required. + * @exception {DeveloperError} semiMajorAxis and semiMinorAxis must be greater than zero. + * @exception {DeveloperError} granularity must be greater than zero. * * @example - * // Create a filled ellipse. - * var polygon = new Polygon(); - * polygon.setPositions(Shapes.computeEllipseBoundary( - * ellipsoid, ellipsoid.cartographicToCartesian( - * Cartographic.fromDegrees(-75.59777, 40.03883)), 500000.0, 300000.0, Math.toRadians(60))); + * // Create an ellipse. + * var ellipsoid = Ellipsoid.WGS84; + * var ellipse = new EllipseGeometry({ + * ellipsoid : ellipsoid, + * center : ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-75.59777, 40.03883)), + * semiMajorAxis : 500000.0, + * semiMinorAxis : 300000.0, + * bearing : CesiumMath.toRadians(60.0) + * }); */ var EllipseGeometry = function(options) { options = defaultValue(options, defaultValue.EMPTY_OBJECT); @@ -391,8 +388,7 @@ define([ * * @see Transforms.eastNorthUpToFixedFrame */ - //this.modelMatrix = defaultValue(options.modelMatrix, Matrix4.IDENTITY.clone()); - this.modelMatrix = Matrix4.IDENTITY.clone(); + this.modelMatrix = defaultValue(options.modelMatrix, Matrix4.IDENTITY.clone()); /** * DOC_TBA From d3253cf6a45c13b4048bd97ee5a2b45c8b562858 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Fri, 24 May 2013 14:34:33 -0400 Subject: [PATCH 080/306] Minimize allocations. Clean up CesiumViewer. --- Apps/CesiumViewer/CesiumViewer.js | 42 ++++++++++++++--------------- Source/Core/EllipseGeometry.js | 44 ++++++++++++++++++------------- 2 files changed, 46 insertions(+), 40 deletions(-) diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index 138a8a119c44..f3b11d94ef0d 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -73,8 +73,8 @@ define([ widget.fullscreen.viewModel.fullscreenElement(document.body); var scene = widget.scene; + var ellipsoid = widget.ellipsoid; - /* var mesh = ExtentTessellator.compute({ extent : new Extent( CesiumMath.toRadians(-180.0), @@ -84,22 +84,11 @@ define([ granularity : 0.006 // More than 64K vertices }); mesh.pickData = 'mesh'; - */ - var ellipsoid = Ellipsoid.WGS84; - var mesh = new EllipseGeometry({ - vertexFormat : VertexFormat.POSITION_ONLY, - ellipsoid : ellipsoid, - center : ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-100, 20)), - semiMinorAxis : 500000.0, - semiMajorAxis : 1000000.0, - bearing : 0.0, - pickData : 'mesh' - }); var mesh2 = new EllipsoidGeometry({ ellipsoid : new Ellipsoid(500000.0, 500000.0, 1000000.0), modelMatrix : Matrix4.multiplyByTranslation(Transforms.eastNorthUpToFixedFrame( - Ellipsoid.WGS84.cartographicToCartesian(Cartographic.fromDegrees(-95.59777, 40.03883))), new Cartesian3(0.0, 0.0, 500000.0)), + ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-95.59777, 40.03883))), new Cartesian3(0.0, 0.0, 500000.0)), pickData : 'mesh2' }); @@ -107,14 +96,25 @@ define([ vertexFormat : VertexFormat.POSITION_ONLY, dimensions : new Cartesian3(1000000.0, 1000000.0, 2000000.0), modelMatrix : Matrix4.multiplyByTranslation(Transforms.eastNorthUpToFixedFrame( - Ellipsoid.WGS84.cartographicToCartesian(Cartographic.fromDegrees(-75.59777, 40.03883))), new Cartesian3(0.0, 0.0, 3000000.0)), + ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-75.59777, 40.03883))), new Cartesian3(0.0, 0.0, 3000000.0)), pickData : 'mesh3' }); + + var mesh4 = new EllipseGeometry({ + vertexFormat : VertexFormat.POSITION_ONLY, + ellipsoid : ellipsoid, + center : ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-100, 20)), + semiMinorAxis : 500000.0, + semiMajorAxis : 1000000.0, + bearing : 0.0, + pickData : 'mesh4' + }); + var primitive = new Primitive({ - geometries : [mesh, mesh2, mesh3], + geometries : [mesh, mesh2, mesh3, mesh4], appearance : Appearance.CLOSED_TRANSLUCENT }); - widget.scene.getPrimitives().add(primitive); + scene.getPrimitives().add(primitive); var m = new Material({ context : widget.scene.getContext(), @@ -151,22 +151,22 @@ define([ renderState : rs }); - var mesh4 = new EllipsoidGeometry({ + var mesh5 = new EllipsoidGeometry({ vertexFormat : VertexFormat.ALL, ellipsoid : new Ellipsoid(1000000.0, 500000.0, 500000.0), modelMatrix : Matrix4.multiplyByTranslation(Transforms.eastNorthUpToFixedFrame( - Ellipsoid.WGS84.cartographicToCartesian(Cartographic.fromDegrees(-75.59777, 40.03883))), new Cartesian3(0.0, 0.0, 4500000.0)), - pickData : 'mesh4' + ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-75.59777, 40.03883))), new Cartesian3(0.0, 0.0, 4500000.0)), + pickData : 'mesh5' }); var primitive2 = new Primitive({ - geometries : mesh4, + geometries : mesh5, appearance :appearance, vertexCacheOptimize : false, releaseGeometries : true, transformToWorldCoordinates : false }); - widget.scene.getPrimitives().add(primitive2); + scene.getPrimitives().add(primitive2); var handler = new ScreenSpaceEventHandler(scene.getCanvas()); handler.setInputAction( diff --git a/Source/Core/EllipseGeometry.js b/Source/Core/EllipseGeometry.js index 209ed179cdf5..cbbfa7dbab02 100644 --- a/Source/Core/EllipseGeometry.js +++ b/Source/Core/EllipseGeometry.js @@ -35,13 +35,12 @@ define([ VertexFormat) { "use strict"; - var position = new Cartesian3(); - var reflectedPosition = new Cartesian3(); - var interiorPosition = new Cartesian3(); - var scratchCart = new Cartographic(); - var normal = new Cartesian3(); - var tangent = new Cartesian3(); - var binormal = new Cartesian3(); + var scratchCartesian1 = new Cartesian3(); + var scratchCartesian2 = new Cartesian3(); + var scratchCartesian3 = new Cartesian3(); + var scratchCartesian4 = new Cartesian3(); + var scratchCartographic = new Cartographic(); + var scratchMatrix2 = new Matrix2(); /** * Computes vertices and indices for an ellipse on the ellipsoid. @@ -124,6 +123,9 @@ define([ positions[2] = 0.0; var positionIndex = 3; + var position = scratchCartesian1; + var reflectedPosition = scratchCartesian2; + for (i = 1; i < numPts; ++i) { var angle = Math.min(i * deltaTheta, CesiumMath.PI_OVER_TWO); @@ -140,7 +142,7 @@ define([ numInterior = 2 * i + 1; for (j = 1; j < numInterior - 1; ++j) { var t = j / (numInterior - 1); - Cartesian3.lerp(position, reflectedPosition, t, interiorPosition); + var interiorPosition = Cartesian3.lerp(position, reflectedPosition, t, scratchCartesian3); positions[positionIndex++] = interiorPosition.x; positions[positionIndex++] = interiorPosition.y; positions[positionIndex++] = interiorPosition.z; @@ -179,13 +181,17 @@ define([ var textureCoordIndex = 0; var projection = new GeographicProjection(ellipsoid); - var centerCart = ellipsoid.cartesianToCartographic(center, scratchCart); - var projectedCenter = projection.project(centerCart); - var rotation = Matrix2.fromRotation(bearing); + var centerCart = ellipsoid.cartesianToCartographic(center, scratchCartographic); + var projectedCenter = projection.project(centerCart, scratchCartesian1); + var rotation = Matrix2.fromRotation(bearing, scratchMatrix2); + + var normal; + var tangent; + var binormal; var length = positions.length; for (i = 0; i < length; i += 3) { - Cartesian3.fromArray(positions, i, position); + position = Cartesian3.fromArray(positions, i, scratchCartesian2); if (vertexFormat.st) { textureCoordinates[textureCoordIndex++] = (position.x + semiMajorAxis) / (2.0 * semiMajorAxis); @@ -195,7 +201,7 @@ define([ Matrix2.multiplyByVector(rotation, position, position); Cartesian2.add(projectedCenter, position, position); - var unprojected = projection.unproject(position, scratchCart); + var unprojected = projection.unproject(position, scratchCartographic); ellipsoid.cartographicToCartesian(unprojected, position); if (vertexFormat.position) { @@ -205,7 +211,7 @@ define([ } if (vertexFormat.normal) { - ellipsoid.geodeticSurfaceNormal(position, normal); + normal = ellipsoid.geodeticSurfaceNormal(position, scratchCartesian3); normals[i] = normal.x; normals[i + 1] = normal.y; @@ -213,8 +219,8 @@ define([ } if (vertexFormat.tangent) { - ellipsoid.geodeticSurfaceNormal(position, normal); - Cartesian3.cross(Cartesian3.UNIT_Z, normal, tangent); + normal = ellipsoid.geodeticSurfaceNormal(position, scratchCartesian3); + tangent = Cartesian3.cross(Cartesian3.UNIT_Z, normal, scratchCartesian3); tangents[i] = tangent.x; tangents[i + 1] = tangent.y; @@ -222,9 +228,9 @@ define([ } if (vertexFormat.binormal) { - ellipsoid.geodeticSurfaceNormal(position, normal); - Cartesian3.cross(Cartesian3.UNIT_Z, normal, tangent); - Cartesian3.cross(normal, tangent, binormal); + normal = ellipsoid.geodeticSurfaceNormal(position, scratchCartesian3); + tangent = Cartesian3.cross(Cartesian3.UNIT_Z, normal, scratchCartesian4); + binormal = Cartesian3.cross(normal, tangent, scratchCartesian3); binormals[i] = binormal.x; binormals[i + 1] = binormal.y; From 9396cfab854332b3923e44fc93ef80fb6be6ea08 Mon Sep 17 00:00:00 2001 From: hpinkos Date: Fri, 24 May 2013 14:50:07 -0400 Subject: [PATCH 081/306] allocation cleanup and exception tests --- CHANGES.md | 3 +- Source/Core/GeometryFilters.js | 119 ++++++------ Specs/Core/GeometryFiltersSpec.js | 289 ++++++++++++++++++++++++++++++ 3 files changed, 348 insertions(+), 63 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index fc56081429c4..b5c73928f6f6 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -17,7 +17,8 @@ Beta Releases * Replaced `Uniform.getFrameNumber` and `Uniform.getTime` with `Uniform.getFrameState`, which returns the full frame state. * Improved the performance of drawing polygons created with `configureFromPolygonHierarchy`. * Added `GeometryFilters.combine` to combine meshes for better batching. -* Added `GeometryFilters.computeNormals` to find the normals of vertices in a mesh. +* Added `GeometryFilters.computeNormal` to find the normals of vertices in a mesh. +* Added `GeometryFilters.computeTangentAndBinormal` to find the tangent and binormal vectors of vertices in a mesh. * Added `BoundingSphere.fromEllipsoid`. * Added renderer support for `OES_element_index_uint`, which can improve performance by reducing batch sizes. * Added `czm_tangentToEyeSpaceMatrix` built-in GLSL function. diff --git a/Source/Core/GeometryFilters.js b/Source/Core/GeometryFilters.js index 2dd853ce4ee7..72619a7be205 100644 --- a/Source/Core/GeometryFilters.js +++ b/Source/Core/GeometryFilters.js @@ -990,12 +990,9 @@ define([ return mesh; }; - var w1 = new Cartesian2(); - var w2 = new Cartesian2(); - var w3 = new Cartesian2(); - var u1 = new Cartesian3(); - var u2 = new Cartesian3(); - var u3 = new Cartesian3(); + var normalScratch = new Cartesian3(); + var normalScale = new Cartesian3(); + var tScratch = new Cartesian3(); GeometryFilters.computeTangentAndBinormal = function(mesh) { if (typeof mesh === 'undefined') { throw new DeveloperError('mesh is required.'); @@ -1023,7 +1020,7 @@ define([ } var st = mesh.attributes.st.values; if (mesh.attributes.st.componentsPerAttribute !== 2 || st.length % 2 !== 0) { - throw new DeveloperError('mesh.attributes.st.values.length must be a multiple of 3'); + throw new DeveloperError('mesh.attributes.st.values.length must be a multiple of 2'); } var indexLists = mesh.indexLists; @@ -1041,57 +1038,49 @@ define([ var numVertices = mesh.attributes.position.values.length/3; var numIndices = indices.length; - var tan1 = new Array(numVertices); + var tan1 = new Array(numVertices*3); + for (var i = 0; i < tan1.length; i++) { - tan1[i] = new Cartesian3(); + tan1[i] = 0; } + var i03, i13, i23; for (i = 0; i < numIndices; i+=3) { var i0 = indices[i]; var i1 = indices[i+1]; var i2 = indices[i+2]; - var i03 = i0*3; - var i13 = i1*3; - var i23 = i2*3; + i03 = i0*3; + i13 = i1*3; + i23 = i2*3; var i02 = i0*2; var i12 = i1*2; var i22 = i2*2; - u1.x = vertices[i03]; - u1.y = vertices[i03+1]; - u1.z = vertices[i03+2]; - u2.x = vertices[i13]; - u2.y = vertices[i13+1]; - u2.z = vertices[i13+2]; - u3.x = vertices[i23]; - u3.y = vertices[i23+1]; - u3.z = vertices[i23+2]; - - w1.x = st[i02]; - w1.y = st[i02+1]; - w2.x = st[i12]; - w2.y = st[i12+1]; - w3.x = st[i22]; - w3.y = st[i22+1]; - - var x1 = u2.x - u1.x; - var x2 = u3.x - u1.x; - var y1 = u2.y - u1.y; - var y2 = u3.y - u1.y; - var z1 = u2.z - u1.z; - var z2 = u3.z - u1.z; - - var s1 = w2.x - w1.x; - var s2 = w3.x - w1.x; - var t1 = w2.y - w1.y; - var t2 = w3.y - w1.y; - - var r = 1.0/(s1 * t2 - s2 * t1); - var sdir = new Cartesian3((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r); - - tan1[i0].add(sdir, tan1[i0]); - tan1[i1].add(sdir, tan1[i1]); - tan1[i2].add(sdir, tan1[i2]); + var ux = vertices[i03]; + var uy = vertices[i03+1]; + var uz = vertices[i03+2]; + + var wx = st[i02]; + var wy = st[i02+1]; + var t1 = st[i12+1] - wy; + var t2 = st[i22+1] - wy; + + var r = 1.0/((st[i12] - wx) * t2 - (st[i22] - wx) * t1); + var sdirx = (t2 * (vertices[i13] - ux) - t1 * (vertices[i23] - ux)) * r; + var sdiry = (t2 * (vertices[i13+1] - uy) - t1 * (vertices[i23+1] - uy)) * r; + var sdirz = (t2 * (vertices[i13+2] - uz) - t1 * (vertices[i23+2] - uz)) * r; + + tan1[i03] += sdirx; + tan1[i03+1] += sdiry; + tan1[i03+2] += sdirz; + + tan1[i13] += sdirx; + tan1[i13+1] += sdiry; + tan1[i13+2] += sdirz; + + tan1[i23] += sdirx; + tan1[i23+1] += sdiry; + tan1[i23+2] += sdirz; } if (typeof mesh.attributes.tangent === 'undefined') { @@ -1109,22 +1098,28 @@ define([ }); } for (i = 0; i < numVertices; i++) { - var i3 = i*3; - var i31 = i3+1; - var i32 = i3+2; - - var n = new Cartesian3(normals[i3], normals[i31], normals[i32]); - var t = tan1[i].normalize(); + i03 = i*3; + i13 = i03+1; + i23 = i03+2; + + var n = normalScratch; + n.x = normals[i03]; + n.y = normals[i13]; + n.z = normals[i23]; + var t = tScratch; + t.x = tan1[i03]; + t.y = tan1[i13]; + t.z = tan1[i23]; var scalar = n.dot(t); - var v = n.multiplyByScalar(scalar); - var tr = (t.subtract(v)).normalize(); - mesh.attributes.tangent.values[i3] = tr.x; - mesh.attributes.tangent.values[i31] = tr.y; - mesh.attributes.tangent.values[i32] = tr.z; - tr = tr.cross(n, tr).normalize(); - mesh.attributes.binormal.values[i3] = tr.x; - mesh.attributes.binormal.values[i31] = tr.y; - mesh.attributes.binormal.values[i32] = tr.z; + n.multiplyByScalar(scalar, normalScale); + t.subtract(normalScale, t).normalize(t); + mesh.attributes.tangent.values[i03] = t.x; + mesh.attributes.tangent.values[i13] = t.y; + mesh.attributes.tangent.values[i23] = t.z; + t.cross(n, t).normalize(t); + mesh.attributes.binormal.values[i03] = t.x; + mesh.attributes.binormal.values[i13] = t.y; + mesh.attributes.binormal.values[i23] = t.z; } } return mesh; diff --git a/Specs/Core/GeometryFiltersSpec.js b/Specs/Core/GeometryFiltersSpec.js index 4e96fe413b98..58c2e8b3342b 100644 --- a/Specs/Core/GeometryFiltersSpec.js +++ b/Specs/Core/GeometryFiltersSpec.js @@ -793,6 +793,295 @@ defineSuite([ expect(mesh.attributes.normal.values.slice(18,21)).toEqual([0, 0, -1]); }); + it('GeometryFilters.computeTangentAndBinormal throws when mesh is undefined', function() { + expect(function() { + GeometryFilters.computeTangentAndBinormal(); + }).toThrow(); + }); + + it('GeometryFilters.computeTangentAndBinormal throws when mesh.attributes is undefined', function() { + expect(function() { + GeometryFilters.computeTangentAndBinormal(new Geometry()); + }).toThrow(); + }); + + it('GeometryFilters.computeTangentAndBinormal throws when mesh.attributes.position is undefined', function() { + expect(function() { + GeometryFilters.computeTangentAndBinormal(new Geometry( { + attributes: {} + })); + }).toThrow(); + }); + + it('GeometryFilters.computeTangentAndBinormal throws when mesh.attributes.position.values is undefined', function() { + expect(function() { + GeometryFilters.computeTangentAndBinormal(new Geometry( { + attributes: { + position: {} + } + })); + }).toThrow(); + }); + + it('GeometryFilters.computeTangentAndBinormal throws when mesh.attributes.position.componentsPerAttribute is not 3', function() { + expect(function() { + GeometryFilters.computeTangentAndBinormal(new Geometry( { + attributes: { + position: { + values: [3, 2, 1, 1, 2, 4], + componentsPerAttribute: 2 + } + } + })); + }).toThrow(); + }); + + it('GeometryFilters.computeTangentAndBinormal throws when mesh.attributes.position.values is not a multiple of 3', function() { + expect(function() { + GeometryFilters.computeTangentAndBinormal(new Geometry( { + attributes: { + position: { + values: [3, 2, 1, 1, 2, 4, 3], + componentsPerAttribute: 3 + } + } + })); + }).toThrow(); + }); + + it('GeometryFilters.computeTangentAndBinormal throws when mesh.attributes.normal is undefined', function() { + expect(function() { + GeometryFilters.computeTangentAndBinormal(new Geometry( { + attributes: { + position: { + values: [0, 0, 0, + 1, 0, 0, + 0, 1, 0], + componentsPerAttribute: 3 + + } + } + })); + }).toThrow(); + }); + + it('GeometryFilters.computeTangentAndBinormal throws when mesh.attributes.normal.values is undefined', function() { + expect(function() { + GeometryFilters.computeTangentAndBinormal(new Geometry( { + attributes: { + position: { + values: [0, 0, 0, + 1, 0, 0, + 0, 1, 0], + componentsPerAttribute: 3 + + }, + normal: {} + } + })); + }).toThrow(); + }); + + it('GeometryFilters.computeTangentAndBinormal throws when mesh.attributes.normal.componentsPerAttribute is not 3', function() { + expect(function() { + GeometryFilters.computeTangentAndBinormal(new Geometry( { + attributes: { + position: { + values: [3, 2, 1, 1, 2, 4], + componentsPerAttribute: 3 + }, + normal: { + values: [3, 2, 1, 1, 2, 4], + componentsPerAttribute: 2 + } + } + })); + }).toThrow(); + }); + + it('GeometryFilters.computeTangentAndBinormal throws when mesh.attributes.normal.values is not a multiple of 3', function() { + expect(function() { + GeometryFilters.computeTangentAndBinormal(new Geometry( { + attributes: { + position: { + values: [3, 2, 1, 1, 2, 3], + componentsPerAttribute: 3 + }, + normal: { + values: [3, 2, 1, 1, 2, 3, 4], + componentsPerAttribute: 3 + } + } + })); + }).toThrow(); + }); + + it('GeometryFilters.computeTangentAndBinormal throws when mesh.attributes.st is undefined', function() { + expect(function() { + GeometryFilters.computeTangentAndBinormal(new Geometry( { + attributes: { + position: { + values: [0, 0, 0, + 1, 0, 0, + 0, 1, 0], + componentsPerAttribute: 3 + + }, + normal: { + values: [0, 0, 0, + 1, 0, 0, + 0, 1, 0], + componentsPerAttribute: 3 + + } + } + })); + }).toThrow(); + }); + + it('GeometryFilters.computeTangentAndBinormal throws when mesh.attributes.normal.values is undefined', function() { + expect(function() { + GeometryFilters.computeTangentAndBinormal(new Geometry( { + attributes: { + position: { + values: [0, 0, 0, + 1, 0, 0, + 0, 1, 0], + componentsPerAttribute: 3 + + }, + normal: { + values: [0, 0, 0, + 1, 0, 0, + 0, 1, 0], + componentsPerAttribute: 3 + + }, + st: {} + } + })); + }).toThrow(); + }); + + it('GeometryFilters.computeTangentAndBinormal throws when mesh.attributes.st.componentsPerAttribute is not 2', function() { + expect(function() { + GeometryFilters.computeTangentAndBinormal(new Geometry( { + attributes: { + position: { + values: [0, 0, 0, + 1, 0, 0, + 0, 1, 0], + componentsPerAttribute: 3 + + }, + normal: { + values: [0, 0, 0, + 1, 0, 0, + 0, 1, 0], + componentsPerAttribute: 3 + + }, + st: { + values: [0, 1], + componentsPerAttribute: 3 + } + } + })); + }).toThrow(); + }); + + it('GeometryFilters.computeTangentAndBinormal throws when mesh.attributes.st.values is not a multiple of 2', function() { + expect(function() { + GeometryFilters.computeTangentAndBinormal(new Geometry( { + attributes: { + position: { + values: [0, 0, 0, + 1, 0, 0, + 0, 1, 0], + componentsPerAttribute: 3 + + }, + normal: { + values: [0, 0, 0, + 1, 0, 0, + 0, 1, 0], + componentsPerAttribute: 3 + + }, + st: { + values: [0, 1, 3], + componentsPerAttribute: 2 + } + } + })); + }).toThrow(); + }); + + + it('GeometryFilters.computeTangentAndBinormal does not compute tangent and binormals when mesh.indexLists is undefined', function() { + var mesh = new Geometry({ + attributes: { + position: { + values: [0, 0, 0, + 1, 0, 0, + 0, 1, 0], + componentsPerAttribute: 3 + + }, + normal: { + values: [0, 0, 0, + 1, 0, 0, + 0, 1, 0], + componentsPerAttribute: 3 + + }, + st: { + values: [0, 1], + componentsPerAttribute: 2 + } + } + }); + + mesh = GeometryFilters.computeTangentAndBinormal(mesh); + + expect(typeof mesh.attributes.tangent === 'undefined').toEqual(true); + expect(typeof mesh.attributes.binormal === 'undefined').toEqual(true); + }); + + it('GeometryFilters.computeTangentAndBinormal does not compute tangent and binormals when primitive type is not triangle', function() { + var mesh = new Geometry({ + attributes: { + position: { + values: [0, 0, 0, + 1, 0, 0, + 0, 1, 0], + componentsPerAttribute: 3 + + }, + normal: { + values: [0, 0, 0, + 1, 0, 0, + 0, 1, 0], + componentsPerAttribute: 3 + + }, + st: { + values: [0, 1], + componentsPerAttribute: 2 + } + }, + indexLists: [{ + primitiveType: PrimitiveType.TRIANGLE_STRIP, + values: [0, 1, 2] + }] + }); + + mesh = GeometryFilters.computeTangentAndBinormal(mesh); + + expect(typeof mesh.attributes.tangent === 'undefined').toEqual(true); + expect(typeof mesh.attributes.binormal === 'undefined').toEqual(true); + }); + it('GeometryFilters.computeTangentAndBinormal computes tangent and binormal for one triangle', function() { var mesh = new Geometry({ attributes: { From 58ec044ad1d053e59a3547618619966b25b281b5 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Fri, 24 May 2013 18:00:51 -0400 Subject: [PATCH 082/306] Comment the process for tessellating an ellipse. --- Source/Core/EllipseGeometry.js | 50 ++++++++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/Source/Core/EllipseGeometry.js b/Source/Core/EllipseGeometry.js index cbbfa7dbab02..9e1c8b8a5636 100644 --- a/Source/Core/EllipseGeometry.js +++ b/Source/Core/EllipseGeometry.js @@ -103,10 +103,29 @@ define([ var vertexFormat = defaultValue(options.vertexFormat, VertexFormat.DEFAULT); + // The number of points in the first quadrant var numPts = Math.ceil(CesiumMath.PI_OVER_TWO / granularity) + 1; var deltaTheta = CesiumMath.PI_OVER_TWO / (numPts - 1); + + // If the number of points were three, the ellipse + // would be tessellated like below: + // + // *---* + // / | \ | \ + // *---*---*---* + // / | \ | \ | \ | \ + // *---*---*---*---*---* + // \ | \ | \ | \ | / + // *---*---*---* + // \ | \ | / + // *---* + // Notice each vertical column contains an odd number of positions. + // The sum of the first n odd numbers is n^2. Double it for the number of points + // for the whole ellipse var size = 2 * numPts * numPts; + // If the ellipsoid contains points on the y axis, remove on of the + // central columns of positions because they would be duplicated. var reachedPiOverTwo = false; if (deltaTheta * (numPts - 1) > CesiumMath.PI_OVER_TWO) { size -= 2 * numPts - 1; @@ -117,6 +136,7 @@ define([ var j; var numInterior; + // Compute the points in the positive x half-space in 2D. var positions = new Array(size * 3); positions[0] = semiMajorAxis; positions[1] = 0.0; @@ -129,9 +149,12 @@ define([ for (i = 1; i < numPts; ++i) { var angle = Math.min(i * deltaTheta, CesiumMath.PI_OVER_TWO); + // Compute the position on the ellipse in the first quadrant. position.x = Math.cos(angle) * semiMajorAxis; position.y = Math.sin(angle) * semiMinorAxis; + // Reflect the position across the x axis for a point on the ellipse + // in the fourth quadrant. reflectedPosition.x = position.x; reflectedPosition.y = -position.y; @@ -139,6 +162,8 @@ define([ positions[positionIndex++] = position.y; positions[positionIndex++] = position.z; + // Compute the points on the interior of the ellipse, on the line + // through the points in the first and fourth quadrants numInterior = 2 * i + 1; for (j = 1; j < numInterior - 1; ++j) { var t = j / (numInterior - 1); @@ -162,6 +187,7 @@ define([ reverseIndex = positionIndex; } + // Reflect the points across the y axis to get the other half of the ellipsoid. for (; i > 0; --i) { numInterior = 2 * i - 1; reverseIndex -= numInterior * 3; @@ -180,6 +206,8 @@ define([ var textureCoordIndex = 0; + // Rotate/translate the positions in the xy-plane and un-project to the ellipsoid in 3D. + // Compute the texture coordinates, normals, tangents, and binormals at the same times. var projection = new GeographicProjection(ellipsoid); var centerCart = ellipsoid.cartesianToCartographic(center, scratchCartographic); var projectedCenter = projection.project(centerCart, scratchCartesian1); @@ -280,18 +308,27 @@ define([ }); } - var indicesSize = numPts * (numPts - 1.0) / 2.0; - indicesSize *= 4.0; - indicesSize += (numPts - 1.0) * 2.0; - indicesSize *= 2.0 * 3.0; + // The number of triangles in the ellipse on the positive x half-space is: + // + // numInteriorTriangles = 4 + 8 + 12 + ... = 4 + (4 + 4) + (4 + 4 + 4) + ... = 4 * (1 + 2 + 3 + ...) + // = 4 * ((n * ( n + 1)) / 2) + // numExteriorTriangles = 2 * n + // + // Substitute (numPts - 1.0) for n above and then: + // + // numTriangles = 2 * (numInteriorTriangles + numExteriorTriangles) + // numIndices = 3 * numTriangles + + var indicesSize = 12.0 * numPts * numPts; if (reachedPiOverTwo) { - indicesSize += (((numPts * 2.0 - 1.0) * 2.0) - 2.0) * 3.0; + indicesSize += 12.0 * (numPts - 1.0); } var indices = new Array(indicesSize); var indicesIndex = 0; var prevIndex; + // Indices for positive x half-space for (i = 0; i < numPts - 1; ++i) { positionIndex = i + 1; positionIndex *= positionIndex; @@ -317,6 +354,7 @@ define([ indices[indicesIndex++] = prevIndex; } + // Indices for central column of triangles (if there is one) if (!reachedPiOverTwo) { numInterior = numPts * 2 - 1; ++positionIndex; @@ -332,6 +370,8 @@ define([ } } + // Reverse the process creating indices for the ellipse on the positive x half-space + // to create the part of the ellipse reflected on the y axis. ++prevIndex; ++positionIndex; for (i = numPts - 1; i > 0; --i) { From 8896208acae2945680d5b1dd7d8ce3edef717c01 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Fri, 24 May 2013 18:20:26 -0400 Subject: [PATCH 083/306] Add tests. --- Specs/Core/CircleGeometrySpec.js | 73 ++++++++++++++++++++++++++++++ Specs/Core/EllipseGeometrySpec.js | 75 +++++++++++++++++++++++++++++++ 2 files changed, 148 insertions(+) create mode 100644 Specs/Core/CircleGeometrySpec.js create mode 100644 Specs/Core/EllipseGeometrySpec.js diff --git a/Specs/Core/CircleGeometrySpec.js b/Specs/Core/CircleGeometrySpec.js new file mode 100644 index 000000000000..1ef1d6e69ba4 --- /dev/null +++ b/Specs/Core/CircleGeometrySpec.js @@ -0,0 +1,73 @@ +/*global defineSuite*/ +defineSuite([ + 'Core/CircleGeometry', + 'Core/Cartesian3', + 'Core/Cartographic', + 'Core/Ellipsoid', + 'Core/VertexFormat' + ], function( + CircleGeometry, + Cartesian3, + Cartographic, + Ellipsoid, + VertexFormat) { + "use strict"; + /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/ + + it('throws without a center', function() { + expect(function() { + return new CircleGeometry({}); + }).toThrow(); + }); + + it('throws with a negative radius', function() { + expect(function() { + return new CircleGeometry({ + center : Cartesian3.UNIT_X, + radius : -1.0 + }); + }).toThrow(); + }); + + it('throws with a negative granularity', function() { + expect(function() { + return new CircleGeometry({ + center : Cartesian3.UNIT_X, + granularity : -1.0 + }); + }).toThrow(); + }); + + it('computes positions', function() { + var ellipsoid = Ellipsoid.WGS84; + var m = new CircleGeometry({ + vertexFormat : VertexFormat.POSITION_ONLY, + ellipsoid : ellipsoid, + center : ellipsoid.cartographicToCartesian(new Cartographic()), + granularity : 0.75, + radius : 1.0 + }); + + expect(m.attributes.position.values.length).toEqual(3 * 32); + expect(m.indexLists[0].values.length).toEqual(3 * 48); + expect(m.boundingSphere.radius).toEqual(1); + }); + + it('compute all vertex attributes', function() { + var ellipsoid = Ellipsoid.WGS84; + var m = new CircleGeometry({ + vertexFormat : VertexFormat.ALL, + ellipsoid : ellipsoid, + center : ellipsoid.cartographicToCartesian(new Cartographic()), + granularity : 0.75, + radius : 1.0 + }); + + expect(m.attributes.position.values.length).toEqual(3 * 32); + expect(m.attributes.st.values.length).toEqual(2 * 32); + expect(m.attributes.normal.values.length).toEqual(3 * 32); + expect(m.attributes.tangent.values.length).toEqual(3 * 32); + expect(m.attributes.binormal.values.length).toEqual(3 * 32); + expect(m.indexLists[0].values.length).toEqual(3 * 48); + }); +}); diff --git a/Specs/Core/EllipseGeometrySpec.js b/Specs/Core/EllipseGeometrySpec.js new file mode 100644 index 000000000000..2dc773d912b5 --- /dev/null +++ b/Specs/Core/EllipseGeometrySpec.js @@ -0,0 +1,75 @@ +/*global defineSuite*/ +defineSuite([ + 'Core/EllipseGeometry', + 'Core/Cartesian3', + 'Core/Cartographic', + 'Core/Ellipsoid', + 'Core/VertexFormat' + ], function( + EllipseGeometry, + Cartesian3, + Cartographic, + Ellipsoid, + VertexFormat) { + "use strict"; + /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/ + + it('throws without a center', function() { + expect(function() { + return new EllipseGeometry({}); + }).toThrow(); + }); + + it('throws with a negative axis', function() { + expect(function() { + return new EllipseGeometry({ + center : Cartesian3.UNIT_X, + semiMajorAxis : -1.0 + }); + }).toThrow(); + }); + + it('throws with a negative granularity', function() { + expect(function() { + return new EllipseGeometry({ + center : Cartesian3.UNIT_X, + granularity : -1.0 + }); + }).toThrow(); + }); + + it('computes positions', function() { + var ellipsoid = Ellipsoid.WGS84; + var m = new EllipseGeometry({ + vertexFormat : VertexFormat.POSITION_ONLY, + ellipsoid : ellipsoid, + center : ellipsoid.cartographicToCartesian(new Cartographic()), + granularity : 0.75, + semiMajorAxis : 1.0, + semiMinorAxis : 1.0 + }); + + expect(m.attributes.position.values.length).toEqual(3 * 32); + expect(m.indexLists[0].values.length).toEqual(3 * 48); + expect(m.boundingSphere.radius).toEqual(1); + }); + + it('compute all vertex attributes', function() { + var ellipsoid = Ellipsoid.WGS84; + var m = new EllipseGeometry({ + vertexFormat : VertexFormat.ALL, + ellipsoid : ellipsoid, + center : ellipsoid.cartographicToCartesian(new Cartographic()), + granularity : 0.75, + semiMajorAxis : 1.0, + semiMinorAxis : 1.0 + }); + + expect(m.attributes.position.values.length).toEqual(3 * 32); + expect(m.attributes.st.values.length).toEqual(2 * 32); + expect(m.attributes.normal.values.length).toEqual(3 * 32); + expect(m.attributes.tangent.values.length).toEqual(3 * 32); + expect(m.attributes.binormal.values.length).toEqual(3 * 32); + expect(m.indexLists[0].values.length).toEqual(3 * 48); + }); +}); From 115fe72fc3768bfa36b54a860f4be8efaa8f9048 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Fri, 24 May 2013 18:21:57 -0400 Subject: [PATCH 084/306] Update CHANGES.md. --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index fc56081429c4..ac92cacc39f5 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -18,6 +18,7 @@ Beta Releases * Improved the performance of drawing polygons created with `configureFromPolygonHierarchy`. * Added `GeometryFilters.combine` to combine meshes for better batching. * Added `GeometryFilters.computeNormals` to find the normals of vertices in a mesh. +* Added `EllipseGeometry` and `CircleGeometry`. * Added `BoundingSphere.fromEllipsoid`. * Added renderer support for `OES_element_index_uint`, which can improve performance by reducing batch sizes. * Added `czm_tangentToEyeSpaceMatrix` built-in GLSL function. From 49356d2f4b29ad1cf92e52d2f6b3c7af06ad57f2 Mon Sep 17 00:00:00 2001 From: Akos Maroy Date: Mon, 27 May 2013 13:39:17 +0200 Subject: [PATCH 085/306] modifications re Patrick Cozzi's git pull reivew feedback --- Apps/Sandcastle/gallery/Polygons.html | 193 ++-- Apps/Sandcastle/gallery/Wall.html | 31 +- .../akosmaroy-2013-03-05-LHTL-LHSK-3d.kml | 874 ------------------ Source/Core/PolygonGeometry.js | 89 +- Source/Core/WallGeometry.js | 188 ++-- Specs/Core/PolygonGeometrySpec.js | 54 -- 6 files changed, 170 insertions(+), 1259 deletions(-) delete mode 100644 Apps/Sandcastle/images/akosmaroy-2013-03-05-LHTL-LHSK-3d.kml diff --git a/Apps/Sandcastle/gallery/Polygons.html b/Apps/Sandcastle/gallery/Polygons.html index 14769239701b..e6ea7dfbd65d 100644 --- a/Apps/Sandcastle/gallery/Polygons.html +++ b/Apps/Sandcastle/gallery/Polygons.html @@ -36,150 +36,103 @@ { "use strict"; - function createAppearance(color) { - var material = Cesium.Material.fromType(undefined, Cesium.Material.ColorType); - material.uniforms.color = color; - var appearance = new Cesium.Appearance({ - renderState : { - cull : { - enabled : false - }, - depthTest : { - enabled : true - }, - depthMask : false, - blending : Cesium.BlendingState.ALPHA_BLEND - }, - material : material - }); - - return appearance; - } - function createPrimitives(widget) { var scene = widget.scene; var ellipsoid = widget.centralBody.getEllipsoid(); var primitives = scene.getPrimitives(); // Create a simple polygon - var polygon = new Cesium.PolygonGeometry({ - positions : ellipsoid.cartographicArrayToCartesianArray([ - Cesium.Cartographic.fromDegrees(-72.0, 40.0), - Cesium.Cartographic.fromDegrees(-70.0, 35.0), - Cesium.Cartographic.fromDegrees(-75.0, 30.0), - Cesium.Cartographic.fromDegrees(-70.0, 30.0), - Cesium.Cartographic.fromDegrees(-68.0, 40.0) - ]), - pickData : 'polygon1' - }); - - var primitive = new Cesium.Primitive({ - geometries : [ polygon ], - appearance : createAppearance(new Cesium.Color(1.0, 1.0, 0.0, 0.75)) - }); - primitives.add(primitive); - - // create a polygon from an extent with rotation - polygon = new Cesium.PolygonGeometry({ - extent : new Cesium.Extent(Cesium.Math.toRadians(-110.0), - Cesium.Math.toRadians(0.0), - Cesium.Math.toRadians(-90.0), - Cesium.Math.toRadians(20.0)), - height : 0.0, - rotation : Cesium.Math.toRadians(45), - pickData : 'polygon2' - }); - - primitive = new Cesium.Primitive({ - geometries : [ polygon ], - appearance : createAppearance({red: 1.0, green: 0.0, blue: 1.0, alpha: 0.75}) - }); - primitives.add(primitive); + var polygon = new Cesium.Polygon(); + Sandcastle.declare(polygon); // For highlighting on mouseover in Sandcastle. + polygon.setPositions(ellipsoid.cartographicArrayToCartesianArray([ + Cesium.Cartographic.fromDegrees(-72.0, 40.0), + Cesium.Cartographic.fromDegrees(-70.0, 35.0), + Cesium.Cartographic.fromDegrees(-75.0, 30.0), + Cesium.Cartographic.fromDegrees(-70.0, 30.0), + Cesium.Cartographic.fromDegrees(-68.0, 40.0) + ])); + primitives.add(polygon); + + polygon = new Cesium.Polygon(); + Sandcastle.declare(polygon); + polygon.configureExtent(new Cesium.Extent( + Cesium.Math.toRadians(-110.0), + Cesium.Math.toRadians(0.0), + Cesium.Math.toRadians(-90.0), + Cesium.Math.toRadians(20.0)), + 0.0, Cesium.Math.toRadians(45)); + polygon.material = Cesium.Material.fromType(scene.getContext(), Cesium.Material.ColorType); + polygon.material.uniforms.color = {red: 1.0, green: 0.0, blue: 1.0, alpha: 0.75}; + primitives.add(polygon); // Create a nested polygon with holes - polygon = new Cesium.PolygonGeometry({ - polygonHierarchy : { + var polygonHierarchy = new Cesium.Polygon(); + Sandcastle.declare(polygonHierarchy); // For highlighting on mouseover in Sandcastle. + + var hierarchy = { + positions : ellipsoid.cartographicArrayToCartesianArray( + [ + Cesium.Cartographic.fromDegrees(-109.0, 30.0), + Cesium.Cartographic.fromDegrees(-95.0, 30.0), + Cesium.Cartographic.fromDegrees(-95.0, 40.0), + Cesium.Cartographic.fromDegrees(-109.0, 40.0) + ]), + holes : [{ positions : ellipsoid.cartographicArrayToCartesianArray( [ - Cesium.Cartographic.fromDegrees(-109.0, 30.0), - Cesium.Cartographic.fromDegrees(-95.0, 30.0), - Cesium.Cartographic.fromDegrees(-95.0, 40.0), - Cesium.Cartographic.fromDegrees(-109.0, 40.0) + Cesium.Cartographic.fromDegrees(-107.0, 31.0), + Cesium.Cartographic.fromDegrees(-107.0, 39.0), + Cesium.Cartographic.fromDegrees(-97.0, 39.0), + Cesium.Cartographic.fromDegrees(-97.0, 31.0) ]), holes : [{ positions : ellipsoid.cartographicArrayToCartesianArray( [ - Cesium.Cartographic.fromDegrees(-107.0, 31.0), - Cesium.Cartographic.fromDegrees(-107.0, 39.0), - Cesium.Cartographic.fromDegrees(-97.0, 39.0), - Cesium.Cartographic.fromDegrees(-97.0, 31.0) + Cesium.Cartographic.fromDegrees(-105.0, 33.0), + Cesium.Cartographic.fromDegrees(-99.0, 33.0), + Cesium.Cartographic.fromDegrees(-99.0, 37.0), + Cesium.Cartographic.fromDegrees(-105.0, 37.0) ]), holes : [{ positions : ellipsoid.cartographicArrayToCartesianArray( [ - Cesium.Cartographic.fromDegrees(-105.0, 33.0), - Cesium.Cartographic.fromDegrees(-99.0, 33.0), - Cesium.Cartographic.fromDegrees(-99.0, 37.0), - Cesium.Cartographic.fromDegrees(-105.0, 37.0) - ]), - holes : [{ - positions : ellipsoid.cartographicArrayToCartesianArray( - [ - Cesium.Cartographic.fromDegrees(-103.0, 34.0), - Cesium.Cartographic.fromDegrees(-101.0, 34.0), - Cesium.Cartographic.fromDegrees(-101.0, 36.0), - Cesium.Cartographic.fromDegrees(-103.0, 36.0) - ]) - }] + Cesium.Cartographic.fromDegrees(-103.0, 34.0), + Cesium.Cartographic.fromDegrees(-101.0, 34.0), + Cesium.Cartographic.fromDegrees(-101.0, 36.0), + Cesium.Cartographic.fromDegrees(-103.0, 36.0) + ]) }] }] - }, - pickData : 'polygon3' - }); - - primitive = new Cesium.Primitive({ - geometries : [ polygon ], - appearance : createAppearance(new Cesium.Color(0.0, 1.0, 1.0, 0.75)) - }); - primitives.add(primitive); + }] + }; + polygonHierarchy.material = Cesium.Material.fromType(scene.getContext(), 'Color'); + polygonHierarchy.material.uniforms.color = new Cesium.Color(0.0, 1.0, 1.0, 0.75); + polygonHierarchy.configureFromPolygonHierarchy(hierarchy); + primitives.add(polygonHierarchy); // Create a polygon from an extent - polygon = new Cesium.PolygonGeometry({ - extent : new Cesium.Extent(Cesium.Math.toRadians(-180.0), - Cesium.Math.toRadians(50.0), - Cesium.Math.toRadians(180.0), - Cesium.Math.toRadians(90.0)), - pickData : 'polygon4' - }); - - primitive = new Cesium.Primitive({ - geometries : [ polygon ], - appearance : createAppearance({red: 1.0, green: 1.0, blue: 0.0, alpha: 0.75}) - }); - primitives.add(primitive); - + var polygonExtent = new Cesium.Polygon(); + Sandcastle.declare(polygonExtent); // For highlighting on mouseover in Sandcastle. + polygonExtent.configureExtent( + new Cesium.Extent( + Cesium.Math.toRadians(-180.0), + Cesium.Math.toRadians(50.0), + Cesium.Math.toRadians(180.0), + Cesium.Math.toRadians(90.0))); + primitives.add(polygonExtent); // Apply a material to a polygon - polygon = new Cesium.PolygonGeometry({ - positions : ellipsoid.cartographicArrayToCartesianArray([ - Cesium.Cartographic.fromDegrees(-90.0, 30.0), - Cesium.Cartographic.fromDegrees(-80.0, 30.0), - Cesium.Cartographic.fromDegrees(-80.0, 40.0), - Cesium.Cartographic.fromDegrees(-90.0, 40.0) - ]), - pickData : 'polygon5' - }); - - var appearance = new Cesium.Appearance({ - material : Cesium.Material.fromType(scene.getContext(), 'Checkerboard') - }); - - primitive = new Cesium.Primitive({ - geometries : [ polygon ], - appearance : appearance - }); - primitives.add(primitive); + var checkeredPolygon = new Cesium.Polygon(); + Sandcastle.declare(checkeredPolygon); // For highlighting on mouseover in Sandcastle. + checkeredPolygon.setPositions(ellipsoid.cartographicArrayToCartesianArray([ + Cesium.Cartographic.fromDegrees(-90.0, 30.0), + Cesium.Cartographic.fromDegrees(-80.0, 30.0), + Cesium.Cartographic.fromDegrees(-80.0, 40.0), + Cesium.Cartographic.fromDegrees(-90.0, 40.0) + ])); + checkeredPolygon.material = Cesium.Material.fromType(scene.getContext(), 'Checkerboard'); + primitives.add(checkeredPolygon); } var widget = new CesiumViewerWidget({ @@ -197,4 +150,4 @@ }); - + \ No newline at end of file diff --git a/Apps/Sandcastle/gallery/Wall.html b/Apps/Sandcastle/gallery/Wall.html index cb1381b549d0..d08d0ef55cd2 100644 --- a/Apps/Sandcastle/gallery/Wall.html +++ b/Apps/Sandcastle/gallery/Wall.html @@ -73,7 +73,7 @@ material : material }); - var coords = [ + var positions = [ new Cesium.Cartographic(Cesium.Math.toRadians(19), Cesium.Math.toRadians(47), 10000), @@ -94,7 +94,7 @@ // create a wall that spans from ground level to 10000 meters var wall1 = new Cesium.WallGeometry({ altitudeMode : 'absolute', - positions : ellipsoid.cartographicArrayToCartesianArray(coords), + positions : ellipsoid.cartographicArrayToCartesianArray(positions), pickData : 'wall1' }); @@ -109,7 +109,7 @@ // create a wall with the same coordinates, but from 15000 - 25000 meters var wall2 = new Cesium.WallGeometry({ altitudeMode : 'absolute', - positions : ellipsoid.cartographicArrayToCartesianArray(coords), + positions : ellipsoid.cartographicArrayToCartesianArray(positions), bottom : 15000, top : 25000, pickData : 'wall2' @@ -124,26 +124,26 @@ // create a wall with a resolution of 0.01 degrees, spanning 1 degree // that will follow the terrain offset above a 1000 meters - coords = []; + positions = []; var res = 0.01; for (var i = 0; i < 1 / res; ++i) { var c = new Cesium.Cartographic(Cesium.Math.toRadians(17 + i * res), Cesium.Math.toRadians(47), 1000); - coords.push(c); + positions.push(c); } var t = []; - for (i = 0; i < coords.length; ++i) { - t[i] = Cesium.Cartographic.clone(coords[i]); + for (i = 0; i < positions.length; ++i) { + t[i] = Cesium.Cartographic.clone(positions[i]); } Cesium.when(Cesium.sampleTerrain(terrainProvider, 11, t), function(terrain) { var wall3 = new Cesium.WallGeometry({ altitudeMode : 'relativeToGround', - positions : ellipsoid.cartographicArrayToCartesianArray(coords), + positions : ellipsoid.cartographicArrayToCartesianArray(positions), terrain : terrain, pickData : 'wall3' }); @@ -156,21 +156,6 @@ primitives.add(p); }); - - // create a wall from a KML LineString - var req = new XMLHttpRequest(); - req.onload = function() { - Cesium.WallGeometry.fromKML(this.responseXML, terrainProvider, function(wall) { - var p = new Cesium.Primitive({ - geometries : [ wall ], - appearance : appearance - }); - - primitives.add(p); - }); - }; - req.open("get", '../images/akosmaroy-2013-03-05-LHTL-LHSK-3d.kml', true); - req.send(); } createPrimitives(widget); diff --git a/Apps/Sandcastle/images/akosmaroy-2013-03-05-LHTL-LHSK-3d.kml b/Apps/Sandcastle/images/akosmaroy-2013-03-05-LHTL-LHSK-3d.kml deleted file mode 100644 index 01e32f07782a..000000000000 --- a/Apps/Sandcastle/images/akosmaroy-2013-03-05-LHTL-LHSK-3d.kml +++ /dev/null @@ -1,874 +0,0 @@ - - - 03/05/13 LHTL-LHSK - 3D View - - - 03/05/13 LHTL-LHSK - 3D View - #flightpath - - 1 - 1 - absolute - -18.9928799,47.3374825,108.8888 -18.9928799,47.3374825,108.94976 -18.9928837,47.3374825,109.1936 -18.9928799,47.3374825,109.22408 -18.9928799,47.3374825,109.0412 -18.9928799,47.3374825,109.0412 -18.9928799,47.3374825,109.346 -18.9928837,47.3374825,109.22408 -18.9928799,47.3374825,108.94976 -18.9928856,47.3374825,108.91928 -18.9928837,47.3374825,108.85832 -18.9928837,47.3374825,108.85832 -18.9928837,47.3374825,108.8888 -18.9928837,47.3374786,108.8888 -18.9928837,47.3374786,108.91928 -18.9928837,47.3374786,108.82784 -18.9928856,47.3374825,108.82784 -18.9928837,47.3374786,108.67544 -18.9928856,47.3374786,108.70592 -18.9928856,47.3374786,108.52304 -18.9928856,47.3374786,108.52304 -18.9928856,47.3374786,108.49256 -18.9928856,47.3374786,108.61448 -18.9928856,47.3374786,108.4316 -18.9928856,47.3374825,108.52304 -18.9928856,47.3374786,108.52304 -18.9928856,47.3374786,108.40112 -18.9928856,47.3374786,108.52304 -18.9928856,47.3374825,108.4316 -18.9928856,47.3374825,108.49256 -18.9928856,47.3374825,108.64496 -18.9928284,47.3374901,108.584 -18.9926281,47.3374939,108.8888 -18.9923820,47.3374252,108.7364 -18.9921074,47.3372917,109.346 -18.9917793,47.3371201,109.346 -18.9914131,47.3369370,109.52888 -18.9910259,47.3368263,109.74224 -18.9906693,47.3368568,109.71176 -18.9906139,47.3368988,109.98608 -18.9906120,47.3368988,110.01656 -18.9904995,47.3369865,110.01656 -18.9891090,47.3381653,110.13848 -18.9878616,47.3392105,110.4128 -18.9864006,47.3405342,111.29672 -18.9846992,47.3419991,121.17224 -18.9829159,47.3435364,136.07696 -18.9811440,47.3451004,161.7716 -18.9797153,47.3463669,182.77232 -18.9776611,47.3481560,205.358 -18.9738159,47.3513412,222.79256 -18.9717865,47.3530617,241.05008 -18.9697704,47.3547096,269.27456 -18.9676800,47.3562927,290.8544 -18.9659195,47.3576126,304.50944 -18.9633121,47.3594894,320.63336 -18.9609356,47.3610916,333.73976 -18.9584579,47.3625793,351.60104 -18.9556198,47.3635788,374.64392 -18.9525986,47.3640480,395.33984 -18.9495506,47.3640366,411.12848 -18.9464779,47.3637772,420.66872 -18.9433651,47.3633690,430.17848 -18.9408531,47.3629303,440.26736 -18.9371738,47.3622627,461.81672 -18.9346943,47.3617668,472.78952 -18.9316044,47.3610649,486.0788 -18.9280968,47.3601494,501.34928 -18.9252472,47.3592453,515.40056 -18.9202175,47.3575249,540.05888 -18.9140663,47.3554077,571.63616 -18.9112453,47.3544388,587.18096 -18.9084339,47.3534813,603.00008 -18.9056110,47.3525200,615.28352 -18.8995743,47.3504524,614.91776 -18.8963146,47.3493080,610.49816 -18.8929195,47.3480759,608.42552 -18.8895607,47.3468361,606.38336 -18.8861523,47.3455505,605.34704 -18.8827686,47.3442497,605.7128 -18.8793640,47.3429413,606.04808 -18.8759556,47.3416100,605.77376 -18.8725376,47.3402824,605.28608 -18.8690987,47.3389397,605.34704 -18.8656864,47.3375969,604.70696 -18.8623295,47.3362732,606.23096 -18.8589458,47.3349495,606.35288 -18.8555679,47.3336182,606.23096 -18.8522282,47.3322906,606.26144 -18.8488216,47.3309326,606.17 -18.8454056,47.3295631,604.55456 -18.8419857,47.3281784,604.37168 -18.8386021,47.3267212,603.2744 -18.8356552,47.3249588,605.8652 -18.8330593,47.3230324,606.07856 -18.8304825,47.3210754,604.31072 -18.8278923,47.3191147,603.18296 -18.8253078,47.3171539,602.93912 -18.8226776,47.3152351,603.39632 -18.8199825,47.3133507,603.76208 -18.8172626,47.3114738,604.06688 -18.8145275,47.3096046,604.21928 -18.8117924,47.3077393,604.21928 -18.8090534,47.3058662,603.85352 -18.8063164,47.3039970,603.39632 -18.8035793,47.3021240,603.09152 -18.8008480,47.3002586,604.06688 -18.7981110,47.2983971,604.06688 -18.7953720,47.2965317,603.94496 -18.7926216,47.2946587,603.18296 -18.7898788,47.2927933,603.09152 -18.7870464,47.2909813,603.5792 -18.7845478,47.2896309,602.17712 -18.7807808,47.2877007,603.15248 -18.7782516,47.2863960,603.76208 -18.7744789,47.2844467,603.70112 -18.7713375,47.2828293,603.51824 -18.7681904,47.2812080,603.39632 -18.7650433,47.2795906,603.15248 -18.7619114,47.2779808,600.62264 -18.7586422,47.2763786,589.49744 -18.7550888,47.2748566,575.26328 -18.7514668,47.2733269,562.33976 -18.7478065,47.2717667,548.80664 -18.7405167,47.2686234,523.44728 -18.7368889,47.2670593,511.77344 -18.7332687,47.2654953,501.19688 -18.7296505,47.2639313,488.33432 -18.7260056,47.2623901,476.75192 -18.7223225,47.2608871,463.3712 -18.7186356,47.2594070,452.76416 -18.7149429,47.2579498,441.7304 -18.7112598,47.2565117,429.5384 -18.7075939,47.2550583,417.71216 -18.7039585,47.2535973,406.43456 -18.7003155,47.2521362,395.30936 -18.6966553,47.2506752,382.38584 -18.6929703,47.2492294,370.1024 -18.6892929,47.2477760,358.00184 -18.6856384,47.2463036,346.66328 -18.6820107,47.2448006,335.08088 -18.6783943,47.2432709,322.82792 -18.6754627,47.2420082,312.4952 -18.6718769,47.2404366,303.8084 -18.6683693,47.2388611,304.44848 -18.6642971,47.2370186,303.56456 -18.6615429,47.2357750,304.7228 -18.6581402,47.2342949,305.942 -18.6547642,47.2328110,305.97248 -18.6481171,47.2298279,308.5328 -18.6447735,47.2283707,306.18584 -18.6414452,47.2269211,309.752 -18.6340828,47.2238197,306.61256 -18.6313229,47.2227058,309.9044 -18.6279144,47.2213058,306.3992 -18.6238689,47.2196045,306.3992 -18.6210804,47.2184525,306.52112 -18.6175976,47.2170601,307.37456 -18.6141205,47.2156334,304.69232 -18.6071377,47.2128105,306.67352 -18.6037064,47.2114143,305.42384 -18.6003170,47.2100410,308.59376 -18.5969334,47.2086716,306.18584 -18.5935459,47.2072868,307.34408 -18.5901966,47.2058754,308.41088 -18.5868340,47.2044792,306.27728 -18.5794601,47.2014275,303.99128 -18.5767593,47.2003098,306.36872 -18.5734310,47.1989555,307.58792 -18.5633640,47.1949120,307.70984 -18.5600071,47.1935120,307.74032 -18.5566063,47.1920891,303.93032 -18.5532188,47.1906815,305.60672 -18.5498276,47.1892776,305.82008 -18.5464401,47.1878929,306.73448 -18.5430241,47.1865349,305.942 -18.5396099,47.1852074,304.53992 -18.5362377,47.1838799,307.466 -18.5329094,47.1825523,307.7708 -18.5263309,47.1798210,310.48352 -18.5230179,47.1784286,306.76496 -18.5196629,47.1770821,306.67352 -18.5162983,47.1757050,307.34408 -18.5129471,47.1743126,306.704 -18.5062294,47.1715698,304.17416 -18.5028534,47.1702232,305.05808 -18.4994678,47.1688995,306.42968 -18.4961052,47.1675606,309.05096 -18.4927368,47.1662064,307.6184 -18.4859467,47.1635094,305.54576 -18.4825478,47.1621475,305.0276 -18.4791756,47.1607475,303.38168 -18.4758167,47.1593590,304.1132 -18.4725246,47.1579742,306.03344 -18.4691944,47.1565666,304.08272 -18.4658184,47.1551895,307.466 -18.4624805,47.1538162,306.73448 -18.4591274,47.1524429,303.74744 -18.4557724,47.1511040,307.25264 -18.4524117,47.1497726,305.75912 -18.4457359,47.1470871,315.51272 -18.4424973,47.1458282,331.2404 -18.4393368,47.1446114,346.54136 -18.4332714,47.1423416,383.72696 -18.4302864,47.1412125,406.43456 -18.4274025,47.1401138,426.24656 -18.4245644,47.1390381,435.6344 -18.4217186,47.1379585,439.71872 -18.4187775,47.1368866,445.93664 -18.4157352,47.1358299,460.0184 -18.4127541,47.1348305,478.94648 -18.4097443,47.1338196,495.5276 -18.4067993,47.1328506,514.21184 -18.4038849,47.1319084,529.48232 -18.3980122,47.1300087,549.1724 -18.3949947,47.1290436,567.94808 -18.3921528,47.1280174,578.67704 -18.3862743,47.1259880,605.98712 -18.3832588,47.1250153,611.0468 -18.3801060,47.1240120,611.74784 -18.3734112,47.1218605,603.51824 -18.3699913,47.1207542,602.90864 -18.3665295,47.1196327,599.70824 -18.3630524,47.1185036,600.2264 -18.3595428,47.1173515,600.40928 -18.3560390,47.1161842,599.95208 -18.3525162,47.1150284,600.2264 -18.3490124,47.1138611,599.89112 -18.3454800,47.1126633,599.55584 -18.3419971,47.1114388,597.45272 -18.3385181,47.1102142,597.9404 -18.3350544,47.1089897,600.5312 -18.3315239,47.1077690,599.49488 -18.3279514,47.1065292,598.21472 -18.3244171,47.1052513,599.09864 -18.3209190,47.1039696,597.90992 -18.3173542,47.1026993,598.36712 -18.3138180,47.1014328,598.03184 -18.3102970,47.1001816,598.82432 -18.3067417,47.0989532,598.73288 -18.3031559,47.0977325,598.33664 -18.2995758,47.0965233,598.33664 -18.2959709,47.0953140,598.94624 -18.2924118,47.0941048,597.90992 -18.2888279,47.0928917,597.30032 -18.2853050,47.0916748,598.03184 -18.2818317,47.0904427,599.58632 -18.2783813,47.0892143,601.26272 -18.2749100,47.0880165,600.34832 -18.2713985,47.0867844,598.00136 -18.2678852,47.0855179,595.89824 -18.2643967,47.0842705,595.502 -18.2608814,47.0830193,596.1116 -18.2574387,47.0817833,600.74456 -18.2539616,47.0804787,595.502 -18.2505074,47.0792122,597.39176 -18.2470150,47.0779877,596.02016 -18.2436199,47.0767212,598.79384 -18.2402954,47.0753937,600.074 -18.2370586,47.0740395,600.3788 -18.2338829,47.0726089,601.41512 -18.2307796,47.0711174,598.97672 -18.2277050,47.0695915,599.0072 -18.2246761,47.0680962,603.36584 -18.2216034,47.0665894,599.49488 -18.2184601,47.0650597,588.9488 -18.2152348,47.0634651,574.53176 -18.2120609,47.0618095,561.73016 -18.2087879,47.0601120,550.63544 -18.2055397,47.0582962,542.68016 -18.2022610,47.0564575,525.94664 -18.1988983,47.0546608,513.44984 -18.1954823,47.0528679,503.4524 -18.1920986,47.0510330,489.7364 -18.1887569,47.0491791,478.64168 -18.1854687,47.0473595,469.22336 -18.1821423,47.0455170,454.86728 -18.1788597,47.0437393,442.7972 -18.1755333,47.0419807,431.48912 -18.1722946,47.0402679,420.91256 -18.1690903,47.0385246,409.90928 -18.1659622,47.0368118,399.2108 -18.1628838,47.0350037,389.3048 -18.1598072,47.0332298,377.63096 -18.1567059,47.0314445,365.86568 -18.1535835,47.0296822,356.11208 -18.1504669,47.0279617,343.28 -18.1473732,47.0262718,332.36816 -18.1443005,47.0245171,321.82208 -18.1411533,47.0228996,328.61912 -18.1375237,47.0217819,333.09968 -18.1292839,47.0216942,331.60616 -18.1251545,47.0223351,328.9544 -18.1210003,47.0230980,322.4012 -18.1168575,47.0239334,320.1152 -18.1126709,47.0248184,318.7436 -18.1086407,47.0256996,320.20664 -18.1045952,47.0264587,321.54776 -18.1004810,47.0270767,317.61584 -18.0963516,47.0276642,317.6768 -18.0923672,47.0282478,326.57696 -18.0883427,47.0287628,329.564 -18.0843945,47.0292549,330.87464 -18.0803928,47.0297318,331.63664 -18.0763931,47.0299911,333.19112 -18.0724087,47.0301361,336.66584 -18.0684280,47.0302658,336.33056 -18.0644302,47.0302582,332.1548 -18.0604210,47.0301437,329.59448 -18.0563335,47.0300255,325.87592 -18.0523129,47.0297813,320.96864 -18.0483093,47.0293579,319.84088 -18.0444260,47.0287323,319.26176 -18.0406322,47.0278893,315.02504 -18.0369530,47.0269203,305.88104 -18.0332355,47.0258408,297.01136 -18.0297642,47.0245018,300.18128 -18.0268364,47.0228271,300.72992 -18.0244980,47.0208435,298.84016 -18.0226364,47.0186920,303.74744 -18.0208149,47.0165710,312.83048 -18.0190907,47.0145302,320.08472 -18.0173397,47.0124969,322.88888 -18.0155811,47.0104523,327.24752 -18.0138531,47.0084724,333.28256 -18.0119896,47.0064850,333.55688 -18.0100441,47.0045166,332.73392 -18.0080261,47.0025215,332.3072 -18.0060291,47.0005455,334.47128 -18.0039730,46.9986076,334.01408 -18.0019226,46.9966087,331.088 -17.9999771,46.9946175,329.19824 -17.9979668,46.9925919,324.77864 -17.9957504,46.9906120,320.1152 -17.9934082,46.9886627,315.14696 -17.9910450,46.9866943,311.76368 -17.9885921,46.9847641,313.4096 -17.9858665,46.9829979,314.41544 -17.9827785,46.9814911,314.84216 -17.9795322,46.9801216,318.62168 -17.9758358,46.9794197,322.8584 -17.9720993,46.9787178,316.3052 -17.9688549,46.9773521,309.56912 -17.9660358,46.9756355,309.17288 -17.9632740,46.9739151,314.56784 -17.9606037,46.9721794,315.90896 -17.9579468,46.9704361,315.87848 -17.9552689,46.9687042,315.32984 -17.9525623,46.9670334,319.99328 -17.9498863,46.9654007,324.77864 -17.9446449,46.9619713,320.90768 -17.9421349,46.9601860,325.87592 -17.9397678,46.9583778,326.0588 -17.9374866,46.9564667,323.80328 -17.9355640,46.9544258,334.98944 -17.9338417,46.9524117,356.17304 -17.9321899,46.9504280,373.88192 -17.9305897,46.9484634,387.35408 -17.9290543,46.9464836,396.9248 -17.9275932,46.9444313,402.19784 -17.9262390,46.9423294,416.00528 -17.9249172,46.9402733,435.11624 -17.9236298,46.9382515,454.13576 -17.9223843,46.9362755,468.8576 -17.9211254,46.9342880,478.27592 -17.9198532,46.9323540,502.72088 -17.9186001,46.9305000,522.9596 -17.9172688,46.9285889,521.16128 -17.9157772,46.9266357,523.53872 -17.9141750,46.9247322,527.62304 -17.9124050,46.9228745,529.208 -17.9107018,46.9210472,531.98168 -17.9090900,46.9192238,544.47848 -17.9077091,46.9174690,564.77816 -17.9064121,46.9157448,581.11544 -17.9027920,46.9127731,601.65896 -17.9005241,46.9114799,599.03768 -17.8979568,46.9101562,596.53832 -17.8949299,46.9090996,604.15832 -17.8913155,46.9091148,607.8464 -17.8879299,46.9104347,599.37296 -17.8855190,46.9127808,582.33464 -17.8826771,46.9148026,596.38592 -17.8790398,46.9152374,617.32568 -17.8757439,46.9144325,604.61552 -17.8724957,46.9132080,573.43448 -17.8691769,46.9118805,554.07968 -17.8657131,46.9105644,543.65552 -17.8622360,46.9092941,528.5984 -17.8587513,46.9079971,506.89664 -17.8552570,46.9066544,487.66376 -17.8517475,46.9052353,469.74152 -17.8482342,46.9038162,454.89776 -17.8447323,46.9024048,442.37048 -17.8412304,46.9010277,427.00856 -17.8377075,46.8997002,411.52472 -17.8341675,46.8984261,397.59536 -17.8306141,46.8972092,384.18416 -17.8270493,46.8959885,365.28656 -17.8234768,46.8947411,351.3572 -17.8199100,46.8934746,337.42784 -17.8162918,46.8922119,322.61456 -17.8126717,46.8909264,307.25264 -17.8090839,46.8896446,299.29736 -17.8055725,46.8884277,297.43808 -17.8021145,46.8872261,301.9796 -17.7986813,46.8860207,302.95496 -17.7953148,46.8847847,301.73576 -17.7919712,46.8835335,303.68648 -17.7886600,46.8822670,305.14952 -17.7853451,46.8810081,304.17416 -17.7820187,46.8797264,301.55288 -17.7786674,46.8784637,300.97376 -17.7753086,46.8772163,302.77208 -17.7719364,46.8759842,302.07104 -17.7685776,46.8747673,301.64432 -17.7652626,46.8735352,304.23512 -17.7619629,46.8722954,303.86936 -17.7586594,46.8710594,305.97248 -17.7553520,46.8698349,302.77208 -17.7520084,46.8686447,304.66184 -17.7486496,46.8674660,305.54576 -17.7452850,46.8662796,304.5704 -17.7419167,46.8650856,303.41216 -17.7385559,46.8638992,304.38752 -17.7351971,46.8627205,304.99712 -17.7318535,46.8615417,304.29608 -17.7285252,46.8603630,305.36288 -17.7252140,46.8591728,306.06392 -17.7218914,46.8579674,305.27144 -17.7185650,46.8567390,304.69232 -17.7152214,46.8554764,305.3324 -17.7118549,46.8542252,302.4368 -17.7084656,46.8529587,300.82136 -17.7050819,46.8516769,300.7604 -17.7017174,46.8503838,300.9128 -17.6983757,46.8491096,301.0652 -17.6949844,46.8478546,300.21176 -17.6915569,46.8466301,300.05936 -17.6881180,46.8454170,302.10152 -17.6846981,46.8441887,301.12616 -17.6813354,46.8429337,302.77208 -17.6779633,46.8417015,302.68064 -17.6745739,46.8404808,302.25392 -17.6711788,46.8392601,301.2176 -17.6677914,46.8380356,302.01008 -17.6644020,46.8368187,301.94912 -17.6610031,46.8356094,301.27856 -17.6576004,46.8344307,299.9984 -17.6542168,46.8332710,299.72408 -17.6508732,46.8321419,302.07104 -17.6475773,46.8310165,305.85056 -17.6442871,46.8298950,307.43552 -17.6409435,46.8287621,305.97248 -17.6375370,46.8276138,302.4368 -17.6340733,46.8264160,297.62096 -17.6305618,46.8252144,295.85312 -17.6270828,46.8240204,294.99968 -17.6236687,46.8228378,300.33368 -17.6202602,46.8216591,300.82136 -17.6168442,46.8204651,297.34664 -17.6134510,46.8192825,298.90112 -17.6100864,46.8181229,299.14496 -17.6067505,46.8169975,304.20464 -17.6034317,46.8158798,306.18584 -17.6000996,46.8147316,301.18712 -17.5967770,46.8135605,300.36416 -17.5934505,46.8123970,300.48608 -17.5901184,46.8112450,299.57168 -17.5867786,46.8100967,299.66312 -17.5834732,46.8089752,300.05936 -17.5802002,46.8078537,302.98544 -17.5769329,46.8067474,304.53992 -17.5736465,46.8056450,304.02176 -17.5703678,46.8045197,303.71696 -17.5671024,46.8033905,306.03344 -17.5638027,46.8022537,303.71696 -17.5604706,46.8010902,302.52824 -17.5571232,46.7999268,299.72408 -17.5537071,46.7989388,310.48352 -17.5501041,46.7986488,326.3636 -17.5465145,46.7991333,330.90512 -17.5396042,46.8012543,342.03032 -17.5363598,46.8025894,353.21648 -17.5334587,46.8042412,362.87864 -17.5311108,46.8063049,363.18344 -17.5291729,46.8085861,359.95256 -17.5272598,46.8109818,359.46488 -17.5254135,46.8134460,360.86696 -17.5235443,46.8159218,361.50704 -17.5217781,46.8184471,364.06736 -17.5200291,46.8209953,364.37216 -17.5182648,46.8235588,362.75672 -17.5164852,46.8261566,365.77424 -17.5147190,46.8287468,368.15168 -17.5130081,46.8313980,364.616 -17.5113869,46.8341026,362.6348 -17.5104389,46.8369179,366.26192 -17.5103130,46.8397560,370.01096 -17.5106525,46.8425941,372.81512 -17.5112133,46.8453331,370.46816 -17.5119877,46.8480721,368.09072 -17.5128059,46.8507957,371.29112 -17.5135612,46.8535042,373.82096 -17.5142822,46.8561707,381.47144 -17.5147533,46.8588371,389.97536 -17.5150127,46.8615341,392.048 -17.5151043,46.8642540,387.7808 -17.5149937,46.8670197,386.47016 -17.5147457,46.8698006,382.38584 -17.5141354,46.8726540,385.61672 -17.5128689,46.8753624,390.6764 -17.5106163,46.8777657,399.94232 -17.5071869,46.8793144,401.192 -17.5034218,46.8795586,403.75232 -17.5003281,46.8785019,409.20824 -17.4964581,46.8749237,399.88136 -17.4958000,46.8728714,404.88008 -17.4962807,46.8708153,407.92808 -17.4978256,46.8689423,404.36192 -17.5003300,46.8675194,412.53056 -17.5034332,46.8666725,415.88336 -17.5069084,46.8666458,413.29256 -17.5102272,46.8677826,411.28088 -17.5125103,46.8699722,400.39952 -17.5127735,46.8728333,391.92608 -17.5105896,46.8786736,388.63424 -17.5092926,46.8816147,380.37416 -17.5080719,46.8845634,375.04016 -17.5075550,46.8875809,378.51488 -17.5080776,46.8904305,378.7892 -17.5103817,46.8959274,380.64848 -17.5099659,46.8987846,389.18288 -17.5077763,46.9011421,385.89104 -17.5041962,46.9024925,374.91824 -17.5002937,46.9023895,375.83264 -17.4969807,46.9012718,368.51744 -17.4942493,46.8996620,368.82224 -17.4915791,46.8979874,372.14456 -17.4889145,46.8962975,375.34496 -17.4861851,46.8946152,377.99672 -17.4834881,46.8929596,378.81968 -17.4808350,46.8912888,385.37288 -17.4782314,46.8896027,386.34824 -17.4757252,46.8879356,389.03048 -17.4732456,46.8862419,388.32944 -17.4708214,46.8845482,388.51232 -17.4683647,46.8828278,386.74448 -17.4658203,46.8810616,381.74576 -17.4633369,46.8792381,381.74576 -17.4608116,46.8774757,380.37416 -17.4582958,46.8756828,380.0084 -17.4557571,46.8739128,377.05184 -17.4531918,46.8721313,371.71784 -17.4506474,46.8703613,366.14 -17.4481258,46.8684540,363.61016 -17.4457188,46.8665466,368.36504 -17.4434204,46.8646660,369.52328 -17.4411163,46.8627319,371.41304 -17.4389801,46.8607254,368.60888 -17.4368076,46.8587685,369.67568 -17.4346733,46.8568306,361.68992 -17.4327335,46.8547592,352.24112 -17.4309349,46.8526268,344.1944 -17.4294090,46.8504372,346.328 -17.4284077,46.8482094,347.05952 -17.4278584,46.8459244,343.64576 -17.4275379,46.8436050,337.24496 -17.4271946,46.8412895,334.80656 -17.4268475,46.8390045,332.4596 -17.4266129,46.8367271,334.10552 -17.4264221,46.8344078,335.14184 -17.4261494,46.8320770,337.09256 -17.4258995,46.8297806,338.4032 -17.4257488,46.8275032,340.29296 -17.4255371,46.8252449,341.78648 -17.4253311,46.8229980,344.59064 -17.4251328,46.8207741,348.09584 -17.4249268,46.8185539,348.27872 -17.4246902,46.8163338,344.804 -17.4243851,46.8140831,340.17104 -17.4241524,46.8118401,341.26832 -17.4239349,46.8096008,340.232 -17.4241791,46.8073845,336.2696 -17.4253998,46.8053169,325.05296 -17.4275627,46.8035660,324.65672 -17.4304256,46.8022652,315.75656 -17.4337788,46.8016090,300.94328 -17.4374371,46.8015442,300.97376 -17.4409981,46.8014259,310.72736 -17.4444866,46.8012733,312.92192 -17.4479980,46.8012199,313.50104 -17.4514980,46.8013039,321.6392 -17.4549751,46.8014679,327.24752 -17.4584503,46.8017197,332.36816 -17.4619064,46.8018837,337.45832 -17.4652710,46.8017502,341.20736 -17.4735241,46.7988091,352.54592 -17.4757195,46.7973251,351.8144 -17.4779148,46.7958221,353.00312 -17.4800854,46.7943039,357.3008 -17.4821434,46.7927246,359.25152 -17.4842415,46.7911339,358.27616 -17.4864788,46.7895470,352.02776 -17.4889450,46.7879410,347.51672 -17.4965153,46.7829971,333.61784 -17.4990959,46.7813034,331.97192 -17.5017052,46.7796440,325.66256 -17.5043125,46.7779770,319.658 -17.5069256,46.7763138,318.34736 -17.5095749,46.7746887,314.59832 -17.5122089,46.7730751,310.87976 -17.5148582,46.7714806,307.6184 -17.5174732,46.7698479,303.1988 -17.5224838,46.7664642,303.89984 -17.5248318,46.7646446,305.69816 -17.5271931,46.7628059,310.23968 -17.5295105,46.7609673,308.95952 -17.5317593,46.7590942,310.72736 -17.5374851,46.7564163,314.1716 -17.5447502,46.7561798,296.55416 -17.5485992,46.7567444,284.54504 -17.5523853,46.7576256,285.73376 -17.5559597,46.7585716,311.00168 -17.5592785,46.7596092,323.40704 -17.5625267,46.7607117,319.44464 -17.5657349,46.7618484,325.26632 -17.5689659,46.7630196,319.99328 -17.5722694,46.7640305,318.46928 -17.5755482,46.7652397,318.40832 -17.5788765,46.7664337,313.95824 -17.5822029,46.7676620,314.08016 -17.5854797,46.7688942,313.62296 -17.5886612,46.7701302,318.62168 -17.5917931,46.7713699,326.54648 -17.5949802,46.7725792,320.32856 -17.5982018,46.7738075,316.7624 -17.6014023,46.7750397,317.76824 -17.6045780,46.7762375,319.77992 -17.6078091,46.7774239,322.82792 -17.6111317,46.7786255,313.80584 -17.6144562,46.7798386,312.98288 -17.6177578,46.7810783,317.15864 -17.6209431,46.7823219,320.8772 -17.6240578,46.7835655,320.17616 -17.6273117,46.7848473,318.19496 -17.6305904,46.7861061,318.92648 -17.6339016,46.7873650,318.07304 -17.6372299,46.7886810,323.22416 -17.6403713,46.7898331,357.02648 -17.6432877,46.7906418,397.41248 -17.6491356,46.7924118,396.80288 -17.6520443,46.7933464,415.9748 -17.6574478,46.7953644,438.9872 -17.6602077,46.7965546,444.29072 -17.6631298,46.7976189,452.48984 -17.6660442,46.7985191,475.07552 -17.6687508,46.7996101,487.69424 -17.6714554,46.8008804,484.95104 -17.6744328,46.8020668,480.8972 -17.6774693,46.8033180,490.55936 -17.6804066,46.8046684,492.632 -17.6867905,46.8071175,480.40952 -17.6899662,46.8084221,480.04376 -17.6963539,46.8108673,486.41408 -17.6994858,46.8120728,488.48672 -17.7026062,46.8132896,483.1832 -17.7090969,46.8157272,463.76744 -17.7126179,46.8170013,462.27392 -17.7160606,46.8182068,457.48856 -17.7195663,46.8193932,455.78168 -17.7231464,46.8204041,452.91656 -17.7266541,46.8215103,459.7136 -17.7301064,46.8226814,469.52816 -17.7334042,46.8238792,463.95032 -17.7366543,46.8253136,451.42304 -17.7400494,46.8266907,445.388 -17.7434368,46.8280029,451.08776 -17.7467365,46.8292236,468.67472 -17.7499352,46.8304367,480.40952 -17.7531204,46.8317184,485.34728 -17.7561512,46.8329926,492.69296 -17.7592220,46.8342361,496.47248 -17.7622261,46.8355789,497.204 -17.7652416,46.8369217,491.99192 -17.7684078,46.8382301,482.54312 -17.7715759,46.8396187,487.11512 -17.7746754,46.8410645,488.33432 -17.7779903,46.8423538,477.72728 -17.7813740,46.8437042,461.32904 -17.7847977,46.8451958,446.33288 -17.7882786,46.8466034,445.57088 -17.7917290,46.8478966,449.13704 -17.7950287,46.8493080,451.3316 -17.7982883,46.8507309,450.63056 -17.8016701,46.8520355,449.89904 -17.8050575,46.8533211,447.18632 -17.8083134,46.8547478,449.71616 -17.8115482,46.8561440,455.7512 -17.8148174,46.8573875,466.78496 -17.8180580,46.8586311,473.03336 -17.8211803,46.8600311,474.16112 -17.8243065,46.8613892,470.71688 -17.8275375,46.8627014,467.54696 -17.8340054,46.8652267,470.534 -17.8372135,46.8665657,473.49056 -17.8404961,46.8677864,466.38872 -17.8438625,46.8690987,451.36208 -17.8473206,46.8704948,436.64024 -17.8508720,46.8718338,434.59808 -17.8542881,46.8730965,462.6092 -17.8608494,46.8754387,466.23632 -17.8641701,46.8766479,464.83424 -17.8706017,46.8789253,474.77072 -17.8739128,46.8799515,468.15656 -17.8773365,46.8810425,454.532 -17.8808002,46.8821564,451.72784 -17.8843594,46.8831139,441.18176 -17.8880501,46.8840179,430.02608 -17.8917065,46.8851166,425.33216 -17.8953571,46.8861809,426.58184 -17.8989563,46.8872414,431.33672 -17.9023838,46.8883743,444.65648 -17.9057503,46.8894005,452.27648 -17.9090614,46.8905029,455.294 -17.9120083,46.8920708,475.53272 -17.9147034,46.8937950,489.1268 -17.9172726,46.8956299,493.27208 -17.9197788,46.8974953,496.53344 -17.9221573,46.8994865,487.84664 -17.9243469,46.9017181,458.89064 -17.9287758,46.9065971,410.6408 -17.9309559,46.9090118,386.68352 -17.9331722,46.9115028,362.69576 -17.9355946,46.9139214,339.07376 -17.9382343,46.9162598,317.12816 -17.9410114,46.9185181,293.07944 -17.9439411,46.9205742,276.0716 -17.9472046,46.9222221,263.5748 -17.9506741,46.9232712,261.38024 -17.9541779,46.9237213,266.53136 -17.9576149,46.9237938,272.44448 -17.9611168,46.9239769,278.60144 -17.9645844,46.9247131,292.50032 -17.9678936,46.9258308,303.59504 -17.9711132,46.9269295,323.71184 -17.9742451,46.9279938,337.09256 -17.9773769,46.9290810,350.35136 -17.9804668,46.9301338,369.82808 -17.9834747,46.9311790,390.2192 -17.9864311,46.9322281,407.19656 -17.9893227,46.9333572,419.84576 -17.9922390,46.9344673,431.3672 -17.9951744,46.9355659,440.17592 -17.9981613,46.9367104,440.26736 -18.0012512,46.9379196,438.3776 -18.0044651,46.9391289,432.1292 -18.0077744,46.9403496,428.59352 -18.0111179,46.9415359,427.34384 -18.0145149,46.9426765,418.77896 -18.0179977,46.9437561,418.19984 -18.0215263,46.9443321,439.10912 -18.0246944,46.9440041,461.26808 -18.0272503,46.9428520,460.90232 -18.0289078,46.9411201,457.06184 -18.0305252,46.9393082,455.11112 -18.0321445,46.9375458,449.25896 -18.0336437,46.9356766,443.07152 -18.0353374,46.9339333,439.50536 -18.0371513,46.9321899,443.52872 -18.0389156,46.9304390,448.55792 -18.0405827,46.9287109,449.22848 -18.0420933,46.9269791,448.92368 -18.0434952,46.9252510,449.41136 -18.0448589,46.9235802,449.41136 -18.0461884,46.9219971,445.47944 -18.0474167,46.9204330,438.95672 -18.0485134,46.9189949,444.56504 -18.0494804,46.9176788,441.30368 -18.0504169,46.9163361,428.38016 -18.0514622,46.9149818,420.05912 -18.0526161,46.9136314,413.10968 -18.0537834,46.9122849,405.03248 -18.0549469,46.9109421,400.06424 -18.0560703,46.9095573,394.15112 -18.0572052,46.9081612,390.40208 -18.0583000,46.9067955,391.7432 -18.0593147,46.9054260,387.11024 -18.0602627,46.9040337,384.7328 -18.0612583,46.9026451,382.56872 -18.0622177,46.9012413,375.61928 -18.0643177,46.8984451,360.83648 -18.0654469,46.8970604,349.9856 -18.0665493,46.8956604,343.4324 -18.0676155,46.8942451,333.13016 -18.0686398,46.8927727,325.4492 -18.0696335,46.8913040,323.34608 -18.0707111,46.8898849,322.0964 -18.0717659,46.8884926,317.12816 -18.0727959,46.8871193,302.4368 -18.0737572,46.8857880,289.57424 -18.0746880,46.8845139,277.71752 -18.0756435,46.8832817,264.36728 -18.0766811,46.8820381,246.07928 -18.0786877,46.8793221,234.22256 -18.0816574,46.8753128,238.2764 -18.0826950,46.8740540,232.66808 -18.0838928,46.8727722,219.74456 -18.0850239,46.8713608,208.31456 -18.0861454,46.8699532,199.14008 -18.0872345,46.8685493,188.04536 -18.0882187,46.8671799,173.6588 -18.0891972,46.8658905,157.6568 -18.0911446,46.8633881,139.09448 -18.0933037,46.8606148,136.1684 -18.0937729,46.8600426,135.92456 -18.0940208,46.8597984,135.68072 -18.0940857,46.8597450,135.80264 -18.0940342,46.8597260,135.7112 -18.0939217,46.8597565,135.68072 -18.0938206,46.8598213,135.61976 -18.0937138,46.8598824,135.58928 -18.0936165,46.8599396,135.61976 -18.0935078,46.8600006,135.52832 -18.0931339,46.8599701,135.19304 -18.0928745,46.8598747,134.91872 -18.0925999,46.8597755,134.70536 -18.0923386,46.8597527,134.61392 -18.0921459,46.8598442,134.61392 -18.0920258,46.8599739,134.55296 -18.0919247,46.8601074,134.70536 -18.0918198,46.8602371,134.76632 -18.0916862,46.8603897,134.6444 -18.0915470,46.8605537,134.6444 -18.0914097,46.8607254,134.9492 -18.0911369,46.8610649,135.16256 -18.0910034,46.8612518,135.13208 -18.0908546,46.8614349,135.4064 -18.0906982,46.8616295,135.68072 -18.0905457,46.8618240,135.80264 -18.0903912,46.8620148,136.016 -18.0900574,46.8624229,136.3208 -18.0898876,46.8626099,136.56464 -18.0897503,46.8627892,136.9304 -18.0895233,46.8628502,136.80848 -18.0892868,46.8627663,136.50368 -18.0890694,46.8627472,136.25984 -18.0889435,46.8628159,136.4732 -18.0888538,46.8628731,136.29032 -18.0887642,46.8629265,136.41224 -18.0886879,46.8629951,136.41224 -18.0886784,46.8630028,136.4732 -18.0886784,46.8630028,136.38176 -18.0886784,46.8630028,136.3208 - - - - - diff --git a/Source/Core/PolygonGeometry.js b/Source/Core/PolygonGeometry.js index c20f6b2cdc21..695a7cdaaf01 100644 --- a/Source/Core/PolygonGeometry.js +++ b/Source/Core/PolygonGeometry.js @@ -19,9 +19,7 @@ define([ './EllipsoidTangentPlane', './WindingOrder', './BoundingRectangle', - './Quaternion', './GeometryFilters', - './ExtentTessellator', './Queue', './Intersect', '../Scene/sampleTerrain', @@ -46,32 +44,31 @@ define([ EllipsoidTangentPlane, WindingOrder, BoundingRectangle, - Quaternion, GeometryFilters, - ExtentTessellator, Queue, Intersect, sampleTerrain, when) { "use strict"; + var ellipsoid; + /** * Creates a PolygonGeometry. The polygon itself is either defined by an array of Cartesian points, - * an extent or a polygon hierarchy. + * or a polygon hierarchy. * * @alias PolygonGeometry * @constructor * - * @param {array of Cartesian} [positions] an array of positions that defined the corner points of the polygon - * @param {Extent} [extent] an extent that defines a polygon. if a rotation attribute is supplied, the extent - * is also rotated + * @param {Array} [positions] an array of positions that defined the corner points of the polygon * @param {polygon hierarchy} [polygonHierarchy] a polygon hierarchy that can include holes - * @param {number} [height=0,0] the height of the polygon, - * @param {radians} [rotation=0.0] if supplied with an extent, the extent is rotated by this angle - * @param {object} [pickData] the geometry pick data + * @param {Number} [height=0.0] the height of the polygon, + * @param {Object} [pickData] the geometry pick data * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] the ellipsoid to be used as a reference * * @exception {DeveloperError} All dimensions components must be greater than or equal to zero. + * @exception {DeveloperError} At least three positions required + * @exception {DeveloperError} positions or polygonHierarchy must be supplied * * @example * @@ -87,17 +84,6 @@ define([ * pickData : 'polygon1' * }); * - * // create a polygon from an extent with rotation - * polygon = new Cesium.PolygonGeometry({ - * extent : new Cesium.Extent(Cesium.Math.toRadians(-110.0), - * Cesium.Math.toRadians(0.0), - * Cesium.Math.toRadians(-90.0), - * Cesium.Math.toRadians(20.0)), - * height : 0.0, - * rotation : Cesium.Math.toRadians(45), - * pickData : 'polygon2' - * }); - * * // create a nested polygon with holes * polygon = new Cesium.PolygonGeometry({ * polygonHierarchy : { @@ -142,46 +128,32 @@ define([ var PolygonGeometry = function(options) { options = defaultValue(options, defaultValue.EMPTY_OBJECT); - var ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84); + ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84); + var meshes = []; var mesh; - var boundingVolume; + var boundingSphere; var i; + var positions; + var polygonHierarchy; if (typeof options.positions !== 'undefined') { // create from positions - this.positions = options.positions; - - boundingVolume = BoundingSphere.fromPoints(this.positions); - mesh = this.createMeshFromPositions(this.positions, boundingVolume); - if (typeof mesh !== 'undefined') { - meshes.push(mesh); - } - - } else if (typeof options.extent !== 'undefined') { - // create from an extent - this.extent = options.extent; - this.rotation = options.rotation; - - boundingVolume = BoundingSphere.fromExtent3D(this.extent, ellipsoid); + positions = options.positions; - mesh = ExtentTessellator.compute({ - extent : this.extent, - rotation : this.rotation, - generateTextureCoordinates : true - }); + boundingSphere = BoundingSphere.fromPoints(positions); + mesh = createMeshFromPositions(positions, boundingSphere); if (typeof mesh !== 'undefined') { meshes.push(mesh); } - } else if (typeof options.polygonHierarchy !== 'undefined') { // create from a polygon hierarchy - this.polygonHierarchy = options.polygonHierarchy; + polygonHierarchy = options.polygonHierarchy; // Algorithm adapted from http://www.geometrictools.com/Documentation/TriangulationByEarClipping.pdf var polygons = []; var queue = new Queue(); - queue.enqueue(this.polygonHierarchy); + queue.enqueue(polygonHierarchy); while (queue.length !== 0) { var outerNode = queue.dequeue(); @@ -216,23 +188,22 @@ define([ } } - this.polygonHierarchy = polygons; + polygonHierarchy = polygons; - var outerPositions = this.polygonHierarchy[0]; + var outerPositions = polygonHierarchy[0]; // The bounding volume is just around the boundary points, so there could be cases for // contrived polygons on contrived ellipsoids - very oblate ones - where the bounding // volume doesn't cover the polygon. - boundingVolume = BoundingSphere.fromPoints(outerPositions); + boundingSphere = BoundingSphere.fromPoints(outerPositions); - for (i = 0; i < this.polygonHierarchy.length; i++) { - mesh = this.createMeshFromPositions(this.polygonHierarchy[i], boundingVolume); + for (i = 0; i < polygonHierarchy.length; i++) { + mesh = createMeshFromPositions(polygonHierarchy[i], boundingSphere); if (typeof mesh !== 'undefined') { meshes.push(mesh); } } - } else { - throw new DeveloperError('positions, extent or hierarchy must be supplied.'); + throw new DeveloperError('positions or hierarchy must be supplied.'); } var attributes = {}; @@ -240,8 +211,6 @@ define([ mesh = GeometryFilters.combine(meshes); mesh = PolygonPipeline.scaleToGeodeticHeight(mesh, defaultValue(options.height, 0.0), ellipsoid); - mesh = GeometryFilters.reorderForPostVertexCache(mesh); - mesh = GeometryFilters.reorderForPreVertexCache(mesh); attributes.position = new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, @@ -273,7 +242,7 @@ define([ /** * The bounding sphere for the whole geometry */ - this.boundingSphere = boundingVolume; + this.boundingSphere = boundingSphere; /** * The model matrix, simply the identity @@ -286,14 +255,14 @@ define([ this.pickData = options.pickData; }; - PolygonGeometry.prototype.createMeshFromPositions = function(positions, boundingSphere, outerPositions) { + function createMeshFromPositions(positions, boundingSphere, outerPositions) { var cleanedPositions = PolygonPipeline.cleanUp(positions); if (cleanedPositions.length < 3) { // Duplicate positions result in not enough positions to form a polygon. return undefined; } - var tangentPlane = EllipsoidTangentPlane.fromPoints(cleanedPositions, this.ellipsoid); + var tangentPlane = EllipsoidTangentPlane.fromPoints(cleanedPositions, ellipsoid); var positions2D = tangentPlane.projectPointsOntoPlane(cleanedPositions); var originalWindingOrder = PolygonPipeline.computeWindingOrder2D(positions2D); @@ -307,10 +276,10 @@ define([ if ((minX < 0) && (BoundingSphere.intersect(boundingSphere, Cartesian4.UNIT_Y) === Intersect.INTERSECTING)) { indices = PolygonPipeline.wrapLongitude(cleanedPositions, indices); } - var mesh = PolygonPipeline.computeSubdivision(cleanedPositions, indices, this._granularity); + var mesh = PolygonPipeline.computeSubdivision(cleanedPositions, indices); return mesh; - }; + } return PolygonGeometry; }); diff --git a/Source/Core/WallGeometry.js b/Source/Core/WallGeometry.js index 2c1e03871cdb..3bc8b2a75aed 100644 --- a/Source/Core/WallGeometry.js +++ b/Source/Core/WallGeometry.js @@ -32,27 +32,58 @@ define([ "use strict"; /** - * Creates a wall, which is similar to a line string. A wall is defined by a series of points, + * Creates a wall, which is similar to a KML line string. A wall is defined by a series of points, * which extrude down to the ground. Optionally they can extrude downwards to a specified height. * The points in the wall can be offset by supplied terrain elevation data. * * @alias WallGeometry * @constructor * - * @param {array of Cartesian} positions an array of Cartesian objects, which are the points of the wall + * @param {Array} positions an array of Cartesian objects, which are the points of the wall * @param {string} altitudeMode either 'absolute' or 'relativeToGround'. 'absolute' means the height * is treated from the WGS84 ellipsoid. 'relativeToGround' means they are treated * relative to the supplied terrain data - * @param {array of Cartesian} [terrain] requred if altitudeMode is 'relativeToGround'. has to denote the same points + * @param {Array} [terrain] requred if altitudeMode is 'relativeToGround'. has to denote the same points * as in positions, with the ground elevation reflecting the terrain elevation - * @param {number} [top] optional, the top of the wall. if specified, the top of the wall is treated as this + * @param {Number} [top] optional, the top of the wall. if specified, the top of the wall is treated as this * height, and the information in the positions array is disregarded - * @param {number} [bottom] optional, the bottom of the wall. if specified, the bottom of the wall is treated as + * @param {Number} [bottom] optional, the bottom of the wall. if specified, the bottom of the wall is treated as * this height. otherwise its treated as 'ground' (the WGS84 ellipsoid height 0) - * @param {object} [pickData] the geometry pick data + * @param {Object} [pickData] the geometry pick data * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] ellispoid for coordinate manipulation * * @exception {DeveloperError} All dimensions components must be greater than or equal to zero. + * @exception {DeveloperError} positions is required + * @exception {DeveloperError} No terrain supplied when required. + * @exception {DeveloperError} Coordinates and terrain points don't match in number + * + * @example + * + * var positions = [ + * new Cesium.Cartographic(Cesium.Math.toRadians(19), + * Cesium.Math.toRadians(47), + * 10000), + * new Cesium.Cartographic(Cesium.Math.toRadians(19), + * Cesium.Math.toRadians(48), + * 10000), + * new Cesium.Cartographic(Cesium.Math.toRadians(20), + * Cesium.Math.toRadians(48), + * 10000), + * new Cesium.Cartographic(Cesium.Math.toRadians(20), + * Cesium.Math.toRadians(47), + * 10000), + * new Cesium.Cartographic(Cesium.Math.toRadians(19), + * Cesium.Math.toRadians(47), + * 10000) + * ]; + * + * // create a wall that spans from ground level to 10000 meters + * var wall1 = new Cesium.WallGeometry({ + * altitudeMode : 'absolute', + * positions : ellipsoid.cartographicArrayToCartesianArray(positions), + * pickData : 'wall1' + * }); + * */ var WallGeometry = function(options) { options = defaultValue(options, defaultValue.EMPTY_OBJECT); @@ -62,7 +93,7 @@ define([ if (typeof options.positions !== 'undefined') { positions = options.positions; } else { - throw new DeveloperError('positions must be supplied.'); + throw new DeveloperError('positions is required.'); } var attributes = {}; @@ -71,7 +102,7 @@ define([ if (options.altitudeMode === 'relativeToGround' && typeof options.terrain === 'undefined') { throw new DeveloperError('No terrain supplied when required.'); } - if (typeof options.terrain !== 'undefined' && options.terrain.length !== options.positions.length) { + if (typeof options.terrain !== 'undefined' && options.terrain.length !== positions.length) { throw new DeveloperError('Coordinates and terrain points don\'t match in number'); } @@ -80,17 +111,18 @@ define([ attributes.position = new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 3, - values : [] + values : new Array(positions.length * 6) }); // add lower and upper points one after the other, lower // points being even and upper points being odd var origHeight; var c; - for (var i = 0; i < options.positions.length; ++i) { - c = ellipsoid.cartesianToCartographic(options.positions[i]); + var values = attributes.position.values; + for (var i = 0, j = 0; i < positions.length; ++i) { + c = ellipsoid.cartesianToCartographic(positions[i]); origHeight = c.height; - c.height = 0; + c.height = 0.0; if (options.bottom !== undefined) { c.height = options.bottom; } @@ -102,9 +134,9 @@ define([ var v = ellipsoid.cartographicToCartesian(c); // insert the lower point - attributes.position.values.push(v.x); - attributes.position.values.push(v.y); - attributes.position.values.push(v.z); + values[j++] = v.x; + values[j++] = v.y; + values[j++] = v.z; // get the original height back, or set the top value c.height = options.top === undefined ? origHeight : options.top; @@ -114,15 +146,17 @@ define([ v = ellipsoid.cartographicToCartesian(c); // insert the upper point - attributes.position.values.push(v.x); - attributes.position.values.push(v.y); - attributes.position.values.push(v.z); + values[j++] = v.x; + values[j++] = v.y; + values[j++] = v.z; } + var noPoints1 = attributes.position.values.length / 3 - 2; + indexLists.push( new GeometryIndices({ primitiveType : PrimitiveType.TRIANGLES, - values : [] + values : new Array(noPoints1 * 3) })); @@ -140,26 +174,20 @@ define([ // C (i) D (i+2) F // - var noPoints1 = attributes.position.values.length / 3 - 2; var indexes = indexLists[0].values; - for (i = 0; i < noPoints1; i += 2) { + for (i = 0, j = 0; i < noPoints1; i += 2) { // first do A C B - indexes.push(i + 1); - indexes.push(i); - indexes.push(i + 3); + indexes[j++] = i + 1; + indexes[j++] = i; + indexes[j++] = i + 3; // now do B C D - indexes.push(i + 3); - indexes.push(i); - indexes.push(i + 2); + indexes[j++] = i + 3; + indexes[j++] = i; + indexes[j++] = i + 2; } - /** - * The ellipsoid used to convert from cartographic to cartesian - */ - this.ellipsoid = ellipsoid; - /** * The attributes (vertices) */ @@ -186,102 +214,6 @@ define([ this.pickData = options.pickData; }; - // default KML namespace resolver, see - // https://developer.mozilla.org/en-US/docs/Introduction_to_using_XPath_in_JavaScript#Implementing_a_User_Defined_Namespace_Resolver - function kmlNsResolver(prefix) { - return 'http://www.opengis.net/kml/2.2'; - } - - /** - * Create a set of Walls from a KML document that includes LineString elements. - * - * @param {DOM node} kmlNode the KML documents document node - * @param {CesiumTerrainProvider} terrainProvider an optional terrain provider for LineStrings that need - * a ground reference. - * @param {function(wall)} callback a function that will receive each WallGeometry created, one at a time. - */ - WallGeometry.fromKML = function kmlReqListener(kmlNode, terrainProvider, callback) { - var name = kmlNode.evaluate('//kml:name', kmlNode, kmlNsResolver, - XPathResult.STRING_TYPE, null); - - var it = kmlNode.evaluate('//kml:LineString', kmlNode, kmlNsResolver, - XPathResult.UNORDERED_NODE_ITERATOR_TYPE, null); - - var addNameToWall = function(wall) { - wall.pickData = name; - callback(wall); - }; - - for (var node = it.iterateNext(); node; node = it.iterateNext()) { - WallGeometry.fromKMLLineString(node, terrainProvider, addNameToWall); - } - }; - - /** - * Create a Wall from a KML LineString DOM element. - * - * @param {DOM node} lineString the KML LineString DOM node to build this Wall from. - * @param {CesiumTerrainProvider} [terrainProvider] an optional terrain provider, used when relative-to-ground elevation - * data is needed to render the wall - * @param {function(wall)} callback the callback that will be called with the created WallGeometry - */ - WallGeometry.fromKMLLineString = function(lineString, terrainProvider, callback) { - var altitudeMode; - var coordinates = []; - - var doc = lineString.ownerDocument; - - // get the coordinates - var xpResult = doc.evaluate('kml:coordinates/text()', lineString, kmlNsResolver, - XPathResult.STRING_TYPE, null); - var coordString = xpResult.stringValue; - var coordSplitWs = coordString.split(/[\s]/); - for (var i = 0; i < coordSplitWs.length; ++i) { - var coordLine = coordSplitWs[i]; - - if (!coordLine.trim()) { - continue; - } - var coordSplit = coordLine.split(','); - - var c = new Cartographic(Math.toRadians(parseFloat(coordSplit[0])), - Math.toRadians(parseFloat(coordSplit[1])), - coordSplit.length < 3 ? 0 : parseFloat(coordSplit[2])); - coordinates.push(c); - } - - // get the altitudeMode flag - xpResult = doc.evaluate('kml:altitudeMode/text()', lineString, kmlNsResolver, - XPathResult.STRING_TYPE, null); - altitudeMode = xpResult.stringValue; - - var options = { - altitudeMode : altitudeMode, - positions : Ellipsoid.WGS84.cartographicArrayToCartesianArray(coordinates) - }; - - if (altitudeMode === 'relativeToGround') { - // request the terrain data for each point of the line string - var coords = []; - - for (i = 0; i < options.positions.length; ++i) { - coords.push(Ellipsoid.WGS84.cartesianToCartographic(options.positions[i])); - } - - // request the elevation ground data - when(sampleTerrain(terrainProvider, 11, coords), function(positions) { - options.terrain = Ellipsoid.WGS84.cartographicArrayToCartesianArray(positions); - - var wall = new WallGeometry(options); - callback(wall); - }); - } else { - // just create a Wall and return it - var wall = new WallGeometry(options); - callback(wall); - } - }; - return WallGeometry; }); diff --git a/Specs/Core/PolygonGeometrySpec.js b/Specs/Core/PolygonGeometrySpec.js index 93efcf1940fd..c9e5c6cebaec 100644 --- a/Specs/Core/PolygonGeometrySpec.js +++ b/Specs/Core/PolygonGeometrySpec.js @@ -13,7 +13,6 @@ defineSuite([ 'Core/Cartesian3', 'Core/Cartographic', 'Core/Ellipsoid', - 'Core/Extent', 'Core/Matrix4', 'Core/Math', 'Core/JulianDate', @@ -37,7 +36,6 @@ defineSuite([ Cartesian3, Cartographic, Ellipsoid, - Extent, Matrix4, CesiumMath, JulianDate, @@ -165,17 +163,6 @@ defineSuite([ }).toThrow(); }); - it('create from extent', function() { - var extent = new Extent( - 0.0, - 0.0, - CesiumMath.toRadians(10.0), - CesiumMath.toRadians(10.0) - ); - - var p = new PolygonGeometry({ extent : extent }); - }); - it('renders', function() { // This test fails in Chrome if a breakpoint is set inside this function. Strange. @@ -192,33 +179,6 @@ defineSuite([ expect(context.readPixels()).not.toEqual([0, 0, 0, 0]); }); - it('renders extent', function() { - // This test fails in Chrome if a breakpoint is set inside this function. Strange. - - var ellipsoid = Ellipsoid.UNIT_SPHERE; - var p = new PolygonGeometry({ - extent : new Extent( - 0.0, - 0.0, - CesiumMath.toRadians(10.0), - CesiumMath.toRadians(10.0) - ), - ellipsoid : ellipsoid - }); - - var material = Material.fromType(undefined, Material.ColorType); - material.uniforms.color = { red : 1.0, green : 0.0, blue : 0.0, alpha : 1.0 }; - var appearance = new Appearance({ material : material }); - - var primitive = new Primitive({ geometries : [ p ], appearance : appearance }); - - ClearCommand.ALL.execute(context); - expect(context.readPixels()).toEqual([0, 0, 0, 0]); - - render(context, frameState, primitive); - expect(context.readPixels()).not.toEqual([0, 0, 0, 0]); - }); - it('does not render when show is false', function() { var material = Material.fromType(undefined, Material.ColorType); material.uniforms.color = { red : 1.0, green : 0.0, blue : 0.0, alpha : 1.0 }; @@ -266,19 +226,5 @@ defineSuite([ }).toThrow(); }); - it('cannot create with empty extent', function() { - var ellipsoid = Ellipsoid.UNIT_SPHERE; - var extent = new Extent( - 0.0, - 0.0, - 0.0, - 0.0 - ); - - expect(function() { - polygon = new PolygonGeometry({ extent : extent, ellipsoid : ellipsoid }); - }).toThrow(); - }); - }, 'WebGL'); From df272cfdafb0473dc2a521127b9f1ad2f8b44107 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Mon, 27 May 2013 11:21:49 -0400 Subject: [PATCH 086/306] Minor cleanup --- Apps/Sandcastle/gallery/Wall.html | 41 +++-------- CHANGES.md | 3 +- Source/Core/BoxGeometry.js | 2 - Source/Core/EllipsoidGeometry.js | 2 - Source/Core/PolygonGeometry.js | 47 +++++------- Source/Core/WallGeometry.js | 59 +++++++-------- Specs/Core/PolygonGeometrySpec.js | 118 +++++++++++++++--------------- Specs/Core/WallGeometrySpec.js | 16 ++-- 8 files changed, 124 insertions(+), 164 deletions(-) diff --git a/Apps/Sandcastle/gallery/Wall.html b/Apps/Sandcastle/gallery/Wall.html index d08d0ef55cd2..a10a97e7ff37 100644 --- a/Apps/Sandcastle/gallery/Wall.html +++ b/Apps/Sandcastle/gallery/Wall.html @@ -50,8 +50,6 @@ }); widget.scene.getPrimitives().getCentralBody().terrainProvider = terrainProvider; - - function createPrimitives(widget) { var scene = widget.scene; var ellipsoid = widget.centralBody.getEllipsoid(); @@ -74,21 +72,11 @@ }); var positions = [ - new Cesium.Cartographic(Cesium.Math.toRadians(19), - Cesium.Math.toRadians(47), - 10000), - new Cesium.Cartographic(Cesium.Math.toRadians(19), - Cesium.Math.toRadians(48), - 10000), - new Cesium.Cartographic(Cesium.Math.toRadians(20), - Cesium.Math.toRadians(48), - 10000), - new Cesium.Cartographic(Cesium.Math.toRadians(20), - Cesium.Math.toRadians(47), - 10000), - new Cesium.Cartographic(Cesium.Math.toRadians(19), - Cesium.Math.toRadians(47), - 10000) + Cesium.Cartographic.fromDegrees(19.0, 47.0, 10000.0), + Cesium.Cartographic.fromDegrees(19.0, 48.0, 10000.0), + Cesium.Cartographic.fromDegrees(20.0, 48.0, 10000.0), + Cesium.Cartographic.fromDegrees(20.0, 47.0, 10000.0), + Cesium.Cartographic.fromDegrees(19.0, 47.0, 10000.0) ]; // create a wall that spans from ground level to 10000 meters @@ -99,13 +87,12 @@ }); var primitive = new Cesium.Primitive({ - geometries : [ wall1 ], + geometries : wall1, appearance : appearance }); primitives.add(primitive); - // create a wall with the same coordinates, but from 15000 - 25000 meters var wall2 = new Cesium.WallGeometry({ altitudeMode : 'absolute', @@ -116,7 +103,7 @@ }); primitive = new Cesium.Primitive({ - geometries : [ wall2 ], + geometries : wall2, appearance : appearance }); @@ -128,9 +115,7 @@ var res = 0.01; for (var i = 0; i < 1 / res; ++i) { - var c = new Cesium.Cartographic(Cesium.Math.toRadians(17 + i * res), - Cesium.Math.toRadians(47), - 1000); + var c = Cesium.Cartographic.fromDegrees(17.0 + i * res, 47.0, 1000.0); positions.push(c); } @@ -140,7 +125,6 @@ } Cesium.when(Cesium.sampleTerrain(terrainProvider, 11, t), function(terrain) { - var wall3 = new Cesium.WallGeometry({ altitudeMode : 'relativeToGround', positions : ellipsoid.cartographicArrayToCartesianArray(positions), @@ -149,23 +133,18 @@ }); var p = new Cesium.Primitive({ - geometries : [ wall3 ], + geometries : wall3, appearance : appearance }); primitives.add(p); }); - } createPrimitives(widget); var camera = widget.scene.getCamera(); - - camera.controller. - setPositionCartographic(new Cesium.Cartographic(Cesium.Math.toRadians(18), - Cesium.Math.toRadians(46), - 20000)); + camera.controller.setPositionCartographic(Cesium.Cartographic.fromDegrees(18.0, 46.0, 20000.0)); camera.controller.lookUp(1.5); Sandcastle.finishedLoading(); diff --git a/CHANGES.md b/CHANGES.md index 0ad11cb9b1dd..f3bde5ba61d1 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -21,8 +21,7 @@ Beta Releases * Added `BoundingSphere.fromEllipsoid`. * Added renderer support for `OES_element_index_uint`, which can improve performance by reducing batch sizes. * Added `czm_tangentToEyeSpaceMatrix` built-in GLSL function. -* Added WallGeometry -* Added PolygonGeometry +* Added `WallGeometry` and `PolygonGeometry`. ### b17 - 2013-06-03 diff --git a/Source/Core/BoxGeometry.js b/Source/Core/BoxGeometry.js index 3970db8d2609..3df6007c03c2 100644 --- a/Source/Core/BoxGeometry.js +++ b/Source/Core/BoxGeometry.js @@ -394,8 +394,6 @@ define([ * by {@link Transforms.eastNorthUpToFixedFrame}. * * @type Matrix4 - * - * @see Transforms.eastNorthUpToFixedFrame */ this.modelMatrix = defaultValue(options.modelMatrix, Matrix4.IDENTITY.clone()); diff --git a/Source/Core/EllipsoidGeometry.js b/Source/Core/EllipsoidGeometry.js index d14fe63f1ca5..baa625fcd447 100644 --- a/Source/Core/EllipsoidGeometry.js +++ b/Source/Core/EllipsoidGeometry.js @@ -343,8 +343,6 @@ define([ * by {@link Transforms.eastNorthUpToFixedFrame}. * * @type Matrix4 - * - * @see Transforms.eastNorthUpToFixedFrame */ this.modelMatrix = defaultValue(options.modelMatrix, Matrix4.IDENTITY.clone()); diff --git a/Source/Core/PolygonGeometry.js b/Source/Core/PolygonGeometry.js index 695a7cdaaf01..0cef36707d9e 100644 --- a/Source/Core/PolygonGeometry.js +++ b/Source/Core/PolygonGeometry.js @@ -1,13 +1,8 @@ /*global define*/ define([ './DeveloperError', - './Cartesian2', - './Cartesian3', './Cartesian4', - './Matrix3', - './Cartographic', './Ellipsoid', - './Math', './Matrix4', './ComponentDatatype', './PrimitiveType', @@ -18,21 +13,13 @@ define([ './PolygonPipeline', './EllipsoidTangentPlane', './WindingOrder', - './BoundingRectangle', './GeometryFilters', './Queue', - './Intersect', - '../Scene/sampleTerrain', - '../ThirdParty/when' + './Intersect' ], function( DeveloperError, - Cartesian2, - Cartesian3, Cartesian4, - Matrix3, - Cartographic, Ellipsoid, - CesiumMath, Matrix4, ComponentDatatype, PrimitiveType, @@ -43,12 +30,9 @@ define([ PolygonPipeline, EllipsoidTangentPlane, WindingOrder, - BoundingRectangle, GeometryFilters, Queue, - Intersect, - sampleTerrain, - when) { + Intersect) { "use strict"; var ellipsoid; @@ -225,32 +209,39 @@ define([ })); /** - * The height of the polygon. - */ - this.height = defaultValue(options.height, 0.0); - - /** - * The attributes (vertices) + * An object containing {@link GeometryAttribute} properties named after each of the + * true values of the {@link VertexFormat} option. + * + * @type Object */ this.attributes = attributes; /** - * The indexes used for GL rendering + * An array of {@link GeometryIndices} defining primitives. + * + * @type Array */ this.indexLists = indexLists; /** - * The bounding sphere for the whole geometry + * A tight-fitting bounding sphere that encloses the vertices of the geometry. + * + * @type BoundingSphere */ this.boundingSphere = boundingSphere; /** - * The model matrix, simply the identity + * The 4x4 transformation matrix that transforms the geometry from model to world coordinates. + * When this is the identity matrix, the geometry is drawn in world coordinates, i.e., Earth's WGS84 coordinates. + * Local reference frames can be used by providing a different transformation matrix, like that returned + * by {@link Transforms.eastNorthUpToFixedFrame}. + * + * @type Matrix4 */ this.modelMatrix = defaultValue(options.modelMatrix, Matrix4.IDENTITY.clone()); /** - * Pick data used for selection + * DOC_TBA */ this.pickData = options.pickData; }; diff --git a/Source/Core/WallGeometry.js b/Source/Core/WallGeometry.js index 3bc8b2a75aed..74a6c7829a93 100644 --- a/Source/Core/WallGeometry.js +++ b/Source/Core/WallGeometry.js @@ -1,34 +1,24 @@ /*global define*/ define([ './DeveloperError', - './Cartesian3', - './Cartographic', './Ellipsoid', - './Math', './Matrix4', './ComponentDatatype', './PrimitiveType', './defaultValue', './BoundingSphere', './GeometryAttribute', - './GeometryIndices', - '../Scene/sampleTerrain', - '../ThirdParty/when' + './GeometryIndices' ], function( DeveloperError, - Cartesian3, - Cartographic, Ellipsoid, - Math, Matrix4, ComponentDatatype, PrimitiveType, defaultValue, BoundingSphere, GeometryAttribute, - GeometryIndices, - sampleTerrain, - when) { + GeometryIndices) { "use strict"; /** @@ -43,7 +33,7 @@ define([ * @param {string} altitudeMode either 'absolute' or 'relativeToGround'. 'absolute' means the height * is treated from the WGS84 ellipsoid. 'relativeToGround' means they are treated * relative to the supplied terrain data - * @param {Array} [terrain] requred if altitudeMode is 'relativeToGround'. has to denote the same points + * @param {Array} [terrain] required if altitudeMode is 'relativeToGround'. has to denote the same points * as in positions, with the ground elevation reflecting the terrain elevation * @param {Number} [top] optional, the top of the wall. if specified, the top of the wall is treated as this * height, and the information in the positions array is disregarded @@ -60,21 +50,11 @@ define([ * @example * * var positions = [ - * new Cesium.Cartographic(Cesium.Math.toRadians(19), - * Cesium.Math.toRadians(47), - * 10000), - * new Cesium.Cartographic(Cesium.Math.toRadians(19), - * Cesium.Math.toRadians(48), - * 10000), - * new Cesium.Cartographic(Cesium.Math.toRadians(20), - * Cesium.Math.toRadians(48), - * 10000), - * new Cesium.Cartographic(Cesium.Math.toRadians(20), - * Cesium.Math.toRadians(47), - * 10000), - * new Cesium.Cartographic(Cesium.Math.toRadians(19), - * Cesium.Math.toRadians(47), - * 10000) + * Cesium.Cartographic.fromDegrees(19.0, 47.0, 10000.0), + * Cesium.Cartographic.fromDegrees(19.0, 48.0, 10000.0), + * Cesium.Cartographic.fromDegrees(20.0, 48.0, 10000.0), + * Cesium.Cartographic.fromDegrees(20.0, 47.0, 10000.0), + * Cesium.Cartographic.fromDegrees(19.0, 47.0, 10000.0) * ]; * * // create a wall that spans from ground level to 10000 meters @@ -176,7 +156,6 @@ define([ var indexes = indexLists[0].values; for (i = 0, j = 0; i < noPoints1; i += 2) { - // first do A C B indexes[j++] = i + 1; indexes[j++] = i; @@ -189,27 +168,39 @@ define([ } /** - * The attributes (vertices) + * An object containing {@link GeometryAttribute} properties named after each of the + * true values of the {@link VertexFormat} option. + * + * @type Object */ this.attributes = attributes; /** - * The indexes used for GL rendering + * An array of {@link GeometryIndices} defining primitives. + * + * @type Array */ this.indexLists = indexLists; /** - * The bounding sphere for the whole geometry + * A tight-fitting bounding sphere that encloses the vertices of the geometry. + * + * @type BoundingSphere */ this.boundingSphere = new BoundingSphere.fromVertices(attributes.position.values); /** - * The model matrix, simply the identity + * The 4x4 transformation matrix that transforms the geometry from model to world coordinates. + * When this is the identity matrix, the geometry is drawn in world coordinates, i.e., Earth's WGS84 coordinates. + * Local reference frames can be used by providing a different transformation matrix, like that returned + * by {@link Transforms.eastNorthUpToFixedFrame}. + * + * @type Matrix4 */ this.modelMatrix = defaultValue(options.modelMatrix, Matrix4.IDENTITY.clone()); /** - * Pick data used for selection + * DOC_TBA */ this.pickData = options.pickData; }; diff --git a/Specs/Core/PolygonGeometrySpec.js b/Specs/Core/PolygonGeometrySpec.js index c9e5c6cebaec..f8e5fb2d30c8 100644 --- a/Specs/Core/PolygonGeometrySpec.js +++ b/Specs/Core/PolygonGeometrySpec.js @@ -8,8 +8,6 @@ defineSuite([ 'Specs/frameState', 'Specs/pick', 'Specs/render', - 'Core/BoundingRectangle', - 'Core/BoundingSphere', 'Core/Cartesian3', 'Core/Cartographic', 'Core/Ellipsoid', @@ -31,8 +29,6 @@ defineSuite([ frameState, pick, render, - BoundingRectangle, - BoundingSphere, Cartesian3, Cartographic, Ellipsoid, @@ -90,33 +86,33 @@ defineSuite([ it('create throws with less than three positions', function() { expect(function() { - var p = new PolygonGeometry({ positions : [new Cartesian3()] }); + return new PolygonGeometry({ positions : [new Cartesian3()] }); }).toThrow(); }); it('create polygon from hierarchy', function() { var hierarchy = { positions : Ellipsoid.WGS84.cartographicArrayToCartesianArray([ - new Cartographic.fromDegrees(-124.0, 35.0, 0.0), - new Cartographic.fromDegrees(-110.0, 35.0, 0.0), - new Cartographic.fromDegrees(-110.0, 40.0, 0.0), - new Cartographic.fromDegrees(-124.0, 40.0, 0.0) + Cartographic.fromDegrees(-124.0, 35.0, 0.0), + Cartographic.fromDegrees(-110.0, 35.0, 0.0), + Cartographic.fromDegrees(-110.0, 40.0, 0.0), + Cartographic.fromDegrees(-124.0, 40.0, 0.0) ]), holes : [{ + positions : Ellipsoid.WGS84.cartographicArrayToCartesianArray([ + Cartographic.fromDegrees(-122.0, 36.0, 0.0), + Cartographic.fromDegrees(-122.0, 39.0, 0.0), + Cartographic.fromDegrees(-112.0, 39.0, 0.0), + Cartographic.fromDegrees(-112.0, 36.0, 0.0) + ]), + holes : [{ positions : Ellipsoid.WGS84.cartographicArrayToCartesianArray([ - new Cartographic.fromDegrees(-122.0, 36.0, 0.0), - new Cartographic.fromDegrees(-122.0, 39.0, 0.0), - new Cartographic.fromDegrees(-112.0, 39.0, 0.0), - new Cartographic.fromDegrees(-112.0, 36.0, 0.0) - ]), - holes : [{ - positions : Ellipsoid.WGS84.cartographicArrayToCartesianArray([ - new Cartographic.fromDegrees(-120.0, 36.5, 0.0), - new Cartographic.fromDegrees(-114.0, 36.5, 0.0), - new Cartographic.fromDegrees(-114.0, 38.5, 0.0), - new Cartographic.fromDegrees(-120.0, 38.5, 0.0) - ]) - }] + Cartographic.fromDegrees(-120.0, 36.5, 0.0), + Cartographic.fromDegrees(-114.0, 36.5, 0.0), + Cartographic.fromDegrees(-114.0, 38.5, 0.0), + Cartographic.fromDegrees(-120.0, 38.5, 0.0) + ]) + }] }] }; @@ -125,28 +121,28 @@ defineSuite([ it('create polygon from clockwise hierarchy', function() { var hierarchy = { + positions : Ellipsoid.WGS84.cartographicArrayToCartesianArray([ + Cartographic.fromDegrees(-124.0, 35.0, 0.0), + Cartographic.fromDegrees(-124.0, 40.0, 0.0), + Cartographic.fromDegrees(-110.0, 40.0, 0.0), + Cartographic.fromDegrees(-110.0, 35.0, 0.0) + ]), + holes : [{ positions : Ellipsoid.WGS84.cartographicArrayToCartesianArray([ - new Cartographic.fromDegrees(-124.0, 35.0, 0.0), - new Cartographic.fromDegrees(-124.0, 40.0, 0.0), - new Cartographic.fromDegrees(-110.0, 40.0, 0.0), - new Cartographic.fromDegrees(-110.0, 35.0, 0.0) + Cartographic.fromDegrees(-122.0, 36.0, 0.0), + Cartographic.fromDegrees(-112.0, 36.0, 0.0), + Cartographic.fromDegrees(-112.0, 39.0, 0.0), + Cartographic.fromDegrees(-122.0, 39.0, 0.0) ]), holes : [{ - positions : Ellipsoid.WGS84.cartographicArrayToCartesianArray([ - new Cartographic.fromDegrees(-122.0, 36.0, 0.0), - new Cartographic.fromDegrees(-112.0, 36.0, 0.0), - new Cartographic.fromDegrees(-112.0, 39.0, 0.0), - new Cartographic.fromDegrees(-122.0, 39.0, 0.0) - ]), - holes : [{ - positions : Ellipsoid.WGS84.cartographicArrayToCartesianArray([ - new Cartographic.fromDegrees(-120.0, 36.5, 0.0), - new Cartographic.fromDegrees(-120.0, 38.5, 0.0), - new Cartographic.fromDegrees(-114.0, 38.5, 0.0), - new Cartographic.fromDegrees(-114.0, 36.5, 0.0) - ]) - }] + positions : Ellipsoid.WGS84.cartographicArrayToCartesianArray([ + Cartographic.fromDegrees(-120.0, 36.5, 0.0), + Cartographic.fromDegrees(-120.0, 38.5, 0.0), + Cartographic.fromDegrees(-114.0, 38.5, 0.0), + Cartographic.fromDegrees(-114.0, 36.5, 0.0) + ]) }] + }] }; var p = new PolygonGeometry({ polygonHierarchy : hierarchy }); @@ -154,12 +150,13 @@ defineSuite([ it('create from PolygonHierarchy throws with less than three positions', function() { var hierarchy = { - positions : Ellipsoid.WGS84.cartographicArrayToCartesianArray([ - new Cartographic() - ]) + positions : Ellipsoid.WGS84.cartographicArrayToCartesianArray([ + new Cartographic() + ]) }; + expect(function() { - var p = new PolygonGeometry({ polygonHierarchy : hierarchy }); + return new PolygonGeometry({ polygonHierarchy : hierarchy }); }).toThrow(); }); @@ -170,7 +167,10 @@ defineSuite([ material.uniforms.color = { red : 1.0, green : 0.0, blue : 0.0, alpha : 1.0 }; var appearance = new Appearance({ material : material }); - var primitive = new Primitive({ geometries : [ polygon ], appearance : appearance }); + var primitive = new Primitive({ + geometries : polygon, + appearance : appearance + }); ClearCommand.ALL.execute(context); expect(context.readPixels()).toEqual([0, 0, 0, 0]); @@ -183,7 +183,10 @@ defineSuite([ var material = Material.fromType(undefined, Material.ColorType); material.uniforms.color = { red : 1.0, green : 0.0, blue : 0.0, alpha : 1.0 }; var appearance = new Appearance({ material : material }); - var primitive = new Primitive({ geometries : [ polygon ], appearance : appearance }); + var primitive = new Primitive({ + geometries : polygon, + appearance : appearance + }); primitive.show = false; expect(render(context, frameState, primitive)).toEqual(0); @@ -208,23 +211,24 @@ defineSuite([ var ellipsoid = Ellipsoid.UNIT_SPHERE; var hierarchy = { positions : ellipsoid.cartographicArrayToCartesianArray([ - new Cartographic.fromDegrees(1.0, 1.0, 0.0), - new Cartographic.fromDegrees(1.0, 1.0, 0.0), - new Cartographic.fromDegrees(1.0, 1.0, 0.0) + Cartographic.fromDegrees(1.0, 1.0, 0.0), + Cartographic.fromDegrees(1.0, 1.0, 0.0), + Cartographic.fromDegrees(1.0, 1.0, 0.0) ]), holes : [{ - positions : ellipsoid.cartographicArrayToCartesianArray([ - new Cartographic.fromDegrees(0.0, 0.0, 0.0), - new Cartographic.fromDegrees(0.0, 0.0, 0.0), - new Cartographic.fromDegrees(0.0, 0.0, 0.0) - ]) + positions : ellipsoid.cartographicArrayToCartesianArray([ + Cartographic.fromDegrees(0.0, 0.0, 0.0), + Cartographic.fromDegrees(0.0, 0.0, 0.0), + Cartographic.fromDegrees(0.0, 0.0, 0.0) + ]) }] }; expect(function() { - polygon = new PolygonGeometry({ polygonHierarchy : hierarchy, ellipsoid : ellipsoid }); + polygon = new PolygonGeometry({ + polygonHierarchy : hierarchy, + ellipsoid : ellipsoid + }); }).toThrow(); }); - - }, 'WebGL'); diff --git a/Specs/Core/WallGeometrySpec.js b/Specs/Core/WallGeometrySpec.js index bf3041fe1fc7..ee977831c093 100644 --- a/Specs/Core/WallGeometrySpec.js +++ b/Specs/Core/WallGeometrySpec.js @@ -21,8 +21,8 @@ defineSuite([ it('create simple absolute', function() { var coords = [ - new Cartographic(49, 18, 1000), - new Cartographic(50, 18, 1000) + Cartographic.fromDegrees(49.0, 18.0, 1000.0), + Cartographic.fromDegrees(50.0, 18.0, 1000.0) ]; var w = new WallGeometry({ @@ -36,8 +36,8 @@ defineSuite([ it('create relative to ground no terrain', function() { var coords = [ - new Cartographic(49, 18, 1000), - new Cartographic(50, 18, 1000) + Cartographic.fromDegrees(49.0, 18.0, 1000.0), + Cartographic.fromDegrees(50.0, 18.0, 1000.0) ]; // this will throw an exception, as no terrain is specified @@ -51,13 +51,13 @@ defineSuite([ it('create relative to ground', function() { var coords = [ - new Cartographic(49, 18, 1000), - new Cartographic(50, 18, 1000) + Cartographic.fromDegrees(49.0, 18.0, 1000.0), + Cartographic.fromDegrees(50.0, 18.0, 1000.0) ]; var terrain = [ - new Cartographic(49, 18, 100), - new Cartographic(50, 18, 110) + Cartographic.fromDegrees(49.0, 18.0, 100.0), + Cartographic.fromDegrees(50.0, 18.0, 110.0) ]; var w = new WallGeometry({ From c14b454ce1c07687cee5e6c8c082ddadcf0cb52a Mon Sep 17 00:00:00 2001 From: hpinkos Date: Tue, 28 May 2013 13:06:57 -0400 Subject: [PATCH 087/306] documentation --- Source/Core/GeometryFilters.js | 111 ++++++++++++++++++++------------- 1 file changed, 69 insertions(+), 42 deletions(-) diff --git a/Source/Core/GeometryFilters.js b/Source/Core/GeometryFilters.js index 72619a7be205..c174dae8702e 100644 --- a/Source/Core/GeometryFilters.js +++ b/Source/Core/GeometryFilters.js @@ -856,7 +856,7 @@ define([ * @exception {DeveloperError} mesh.attributes.position.values.length must be a multiple of 3 * * @example - * mesh = GeometryFilters.computeNormals(mesh); + * mesh = GeometryFilters.computeNormal(mesh); * */ var normal = new Cartesian3(); @@ -990,42 +990,64 @@ define([ return mesh; }; + /** + * Computes the tangent and binormal of all vertices in a geometry + * This assumes a counter-clockwise vertex winding order. + * + * @param {Geometry} geometry The geometry for which to calculate tangents and binormals, which is modified in place. + * @param {Object} geometry.attributes.position The vertices of the geometry + * @param {Object} geometry.attributes.normal The normals of the vertices + * @param {Object} geometry.attributes.st The texture coordinates + * + * @returns The modified geometry argument. + * + * @exception {DeveloperError} geometry.attributes.position.values is required + * @exception {DeveloperError} geometry.attributes.position.values.length must be a multiple of 3 + * @exception {DeveloperError} geometry.attributes.normal.values is required + * @exception {DeveloperError} geometry.attributes.normal.values.length must be a multiple of 3 + * @exception {DeveloperError} geometry.attributes.st.values is required + * @exception {DeveloperError} geometry.attributes.st.values.length must be a multiple of 2 + * + * @example + * geometry = GeometryFilters.computeTangentAndBinormal(geometry); + * + */ var normalScratch = new Cartesian3(); var normalScale = new Cartesian3(); var tScratch = new Cartesian3(); - GeometryFilters.computeTangentAndBinormal = function(mesh) { - if (typeof mesh === 'undefined') { - throw new DeveloperError('mesh is required.'); + GeometryFilters.computeTangentAndBinormal = function(geometry) { + if (typeof geometry === 'undefined') { + throw new DeveloperError('geometry is required.'); } - var attributes = mesh.attributes; + var attributes = geometry.attributes; if (typeof attributes === 'undefined' || typeof attributes.position === 'undefined' || typeof attributes.position.values === 'undefined') { - throw new DeveloperError('mesh.attributes.position.values is required'); + throw new DeveloperError('geometry.attributes.position.values is required'); } - var vertices = mesh.attributes.position.values; - if (mesh.attributes.position.componentsPerAttribute !== 3 || vertices.length % 3 !== 0) { - throw new DeveloperError('mesh.attributes.position.values.length must be a multiple of 3'); + var vertices = geometry.attributes.position.values; + if (geometry.attributes.position.componentsPerAttribute !== 3 || vertices.length % 3 !== 0) { + throw new DeveloperError('geometry.attributes.position.values.length must be a multiple of 3'); } if (typeof attributes.normal === 'undefined' || typeof attributes.normal.values === 'undefined') { - throw new DeveloperError('mesh.attributes.normal.values is required'); + throw new DeveloperError('geometry.attributes.normal.values is required'); } - var normals = mesh.attributes.normal.values; - if (mesh.attributes.normal.componentsPerAttribute !== 3 || normals.length % 3 !== 0) { - throw new DeveloperError('mesh.attributes.normals.values.length must be a multiple of 3'); + var normals = geometry.attributes.normal.values; + if (geometry.attributes.normal.componentsPerAttribute !== 3 || normals.length % 3 !== 0) { + throw new DeveloperError('geometry.attributes.normals.values.length must be a multiple of 3'); } if (typeof attributes.st === 'undefined' || typeof attributes.st.values === 'undefined') { - throw new DeveloperError('mesh.attributes.st.values is required'); + throw new DeveloperError('geometry.attributes.st.values is required'); } - var st = mesh.attributes.st.values; - if (mesh.attributes.st.componentsPerAttribute !== 2 || st.length % 2 !== 0) { - throw new DeveloperError('mesh.attributes.st.values.length must be a multiple of 2'); + var st = geometry.attributes.st.values; + if (geometry.attributes.st.componentsPerAttribute !== 2 || st.length % 2 !== 0) { + throw new DeveloperError('geometry.attributes.st.values.length must be a multiple of 2'); } - var indexLists = mesh.indexLists; + var indexLists = geometry.indexLists; if (typeof indexLists === 'undefined') { - return mesh; + return geometry; } var length = indexLists.length; @@ -1036,7 +1058,7 @@ define([ continue; } - var numVertices = mesh.attributes.position.values.length/3; + var numVertices = geometry.attributes.position.values.length/3; var numIndices = indices.length; var tan1 = new Array(numVertices*3); @@ -1082,21 +1104,8 @@ define([ tan1[i23+1] += sdiry; tan1[i23+2] += sdirz; } - - if (typeof mesh.attributes.tangent === 'undefined') { - mesh.attributes.tangent = new GeometryAttribute({ - componentDatatype: ComponentDatatype.FLOAT, - componentsPerAttribute: 3, - values: new Array(numVertices * 3) - }); - } - if (typeof mesh.attributes.binormal === 'undefined') { - mesh.attributes.binormal = new GeometryAttribute({ - componentDatatype: ComponentDatatype.FLOAT, - componentsPerAttribute: 3, - values: new Array(numVertices * 3) - }); - } + var binormalValues = new Array(numVertices * 3); + var tangentValues = new Array(numVertices * 3); for (i = 0; i < numVertices; i++) { i03 = i*3; i13 = i03+1; @@ -1113,16 +1122,34 @@ define([ var scalar = n.dot(t); n.multiplyByScalar(scalar, normalScale); t.subtract(normalScale, t).normalize(t); - mesh.attributes.tangent.values[i03] = t.x; - mesh.attributes.tangent.values[i13] = t.y; - mesh.attributes.tangent.values[i23] = t.z; + tangentValues[i03] = t.x; + tangentValues[i13] = t.y; + tangentValues[i23] = t.z; t.cross(n, t).normalize(t); - mesh.attributes.binormal.values[i03] = t.x; - mesh.attributes.binormal.values[i13] = t.y; - mesh.attributes.binormal.values[i23] = t.z; + binormalValues[i03] = t.x; + binormalValues[i13] = t.y; + binormalValues[i23] = t.z; + } + if (typeof geometry.attributes.tangent === 'undefined') { + geometry.attributes.tangent = new GeometryAttribute({ + componentDatatype: ComponentDatatype.FLOAT, + componentsPerAttribute: 3, + values: tangentValues + }); + } else { + geometry.attributes.tangent.values = tangentValues; + } + if (typeof geometry.attributes.binormal === 'undefined') { + geometry.attributes.binormal = new GeometryAttribute({ + componentDatatype: ComponentDatatype.FLOAT, + componentsPerAttribute: 3, + values: binormalValues + }); + } else { + geometry.attributes.binormal.values = binormalValues; } } - return mesh; + return geometry; }; return GeometryFilters; From f5ac943f04283af8a0b6c70c5573f23a5677f0ee Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Tue, 28 May 2013 13:51:42 -0400 Subject: [PATCH 088/306] Change Extent.subsample and BoundingSphere.fromExtent3D to use a height parameter. Add tests. Update CHANGES.md. --- CHANGES.md | 2 ++ Source/Core/BoundingSphere.js | 18 ++---------------- Source/Core/EllipsoidalOccluder.js | 2 +- Source/Core/Extent.js | 17 ++--------------- Source/Core/ExtentGeometry.js | 2 +- Source/Core/Occluder.js | 2 +- Specs/Core/BoundingSphereSpec.js | 9 +++++++++ Specs/Core/ExtentSpec.js | 26 +++++++++++++++++++++++++- 8 files changed, 43 insertions(+), 35 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 3ebc7cc85b90..7b3b31a2cc77 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -20,6 +20,8 @@ Beta Releases * Added `GeometryFilters.combine` to combine meshes for better batching. * Added `GeometryFilters.computeNormals` to find the normals of vertices in a mesh. * Added `BoundingSphere.fromEllipsoid`. +* Added `height` parameter to `BoundingSphere.fromExtent3D`. +* Added `height` parameter to `Extent.subsample`. * Added renderer support for `OES_element_index_uint`, which can improve performance by reducing batch sizes. * Added `czm_tangentToEyeSpaceMatrix` built-in GLSL function. * Added `WallGeometry` and `PolygonGeometry`. diff --git a/Source/Core/BoundingSphere.js b/Source/Core/BoundingSphere.js index d9a363fc2596..a38bae8e416b 100644 --- a/Source/Core/BoundingSphere.js +++ b/Source/Core/BoundingSphere.js @@ -287,31 +287,17 @@ define([ * * @param {Extent} extent The valid extent used to create a bounding sphere. * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid used to determine positions of the extent. - * @param {BoundingSphere} [result] The object onto which to store the result. - * @return {BoundingSphere} The modified result parameter or a new BoundingSphere instance if none was provided. - */ - BoundingSphere.fromExtent3D = function(extent, ellipsoid, result) { - return BoundingSphere.fromExtentWithHeight3D(extent, ellipsoid, 0.0, result); - }; - - /** - * Computes a bounding sphere from an extent at a given height in 3D. The bounding sphere is created using a subsample of points - * above the ellipsoid and contained in the extent. It may not be accurate for all extents on all types of ellipsoids. - * @memberof BoundingSphere - * - * @param {Extent} extent The valid extent used to create a bounding sphere. - * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid used to determine positions of the extent. * @param {Number} [surfaceHeight=0.0] The height above the surface of the ellipsoid. * @param {BoundingSphere} [result] The object onto which to store the result. * @return {BoundingSphere} The modified result parameter or a new BoundingSphere instance if none was provided. */ - BoundingSphere.fromExtentWithHeight3D = function(extent, ellipsoid, surfaceHeight, result) { + BoundingSphere.fromExtent3D = function(extent, ellipsoid, surfaceHeight, result) { ellipsoid = defaultValue(ellipsoid, Ellipsoid.WGS84); surfaceHeight = defaultValue(surfaceHeight, 0.0); var positions; if (typeof extent !== 'undefined') { - positions = extent.subsampleWithHeight(ellipsoid, surfaceHeight, fromExtent3DScratch); + positions = extent.subsample(ellipsoid, surfaceHeight, fromExtent3DScratch); } return BoundingSphere.fromPoints(positions, result); diff --git a/Source/Core/EllipsoidalOccluder.js b/Source/Core/EllipsoidalOccluder.js index aaade38b5af4..a4c7f5b9cbb0 100644 --- a/Source/Core/EllipsoidalOccluder.js +++ b/Source/Core/EllipsoidalOccluder.js @@ -259,7 +259,7 @@ define([ throw new DeveloperError('extent is required.'); } - var positions = extent.subsample(ellipsoid, subsampleScratch); + var positions = extent.subsample(ellipsoid, 0.0, subsampleScratch); var bs = BoundingSphere.fromPoints(positions); // If the bounding sphere center is too close to the center of the occluder, it doesn't make diff --git a/Source/Core/Extent.js b/Source/Core/Extent.js index fa2b24025029..4f1e47bdf7ba 100644 --- a/Source/Core/Extent.js +++ b/Source/Core/Extent.js @@ -354,22 +354,9 @@ define([ return this.west >= this.east || this.south >= this.north; }; - /** - * Samples this Extent so that it includes a list of Cartesian points suitable for passing to - * {@link BoundingSphere#fromPoints}. Sampling is necessary to account - * for extents that cover the poles or cross the equator. - * - * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid to use. - * @param {Array} [result] The array of Cartesians onto which to store the result. - * @return {Array} The modified result parameter or a new Array of Cartesians instances if none was provided. - */ - Extent.prototype.subsample = function(ellipsoid, result) { - return this.subsampleWithHeight(ellipsoid, 0.0, result); - }; - var subsampleLlaScratch = new Cartographic(); /** - * Samples this Extent at a height above the ellipsoid so that it includes a list of Cartesian points suitable for passing to + * Samples this extent so that it includes a list of Cartesian points suitable for passing to * {@link BoundingSphere#fromPoints}. Sampling is necessary to account * for extents that cover the poles or cross the equator. * @@ -378,7 +365,7 @@ define([ * @param {Array} [result] The array of Cartesians onto which to store the result. * @return {Array} The modified result parameter or a new Array of Cartesians instances if none was provided. */ - Extent.prototype.subsampleWithHeight = function(ellipsoid, surfaceHeight, result) { + Extent.prototype.subsample = function(ellipsoid, surfaceHeight, result) { ellipsoid = defaultValue(ellipsoid, Ellipsoid.WGS84); surfaceHeight = defaultValue(surfaceHeight, 0.0); diff --git a/Source/Core/ExtentGeometry.js b/Source/Core/ExtentGeometry.js index 91ade1a917f1..ed09bf68da74 100644 --- a/Source/Core/ExtentGeometry.js +++ b/Source/Core/ExtentGeometry.js @@ -317,7 +317,7 @@ define([ * * @type BoundingSphere */ - this.boundingSphere = BoundingSphere.fromExtentWithHeight3D(extent, ellipsoid, surfaceHeight); + this.boundingSphere = BoundingSphere.fromExtent3D(extent, ellipsoid, surfaceHeight); /** * The 4x4 transformation matrix that transforms the geometry from model to world coordinates. diff --git a/Source/Core/Occluder.js b/Source/Core/Occluder.js index 5564fbb6bb78..a234fc63a725 100644 --- a/Source/Core/Occluder.js +++ b/Source/Core/Occluder.js @@ -374,7 +374,7 @@ define([ } ellipsoid = defaultValue(ellipsoid, Ellipsoid.WGS84); - var positions = extent.subsample(ellipsoid, computeOccludeePointFromExtentScratch); + var positions = extent.subsample(ellipsoid, 0.0, computeOccludeePointFromExtentScratch); var bs = BoundingSphere.fromPoints(positions); // TODO: get correct ellipsoid center diff --git a/Specs/Core/BoundingSphereSpec.js b/Specs/Core/BoundingSphereSpec.js index f9d1ec211052..2e8ff3765c05 100644 --- a/Specs/Core/BoundingSphereSpec.js +++ b/Specs/Core/BoundingSphereSpec.js @@ -287,6 +287,15 @@ defineSuite([ expect(BoundingSphere.fromExtent3D(extent, ellipsoid)).toEqual(expected); }); + it('fromExtent3D with height', function() { + var extent = new Extent(0.1, -0.3, 0.2, -0.4); + var height = 100000.0; + var ellipsoid = Ellipsoid.WGS84; + var points = extent.subsample(ellipsoid, height); + var expected = BoundingSphere.fromPoints(points); + expect(BoundingSphere.fromExtent3D(extent, ellipsoid, height)).toEqual(expected); + }); + it('fromCornerPoints', function() { var sphere = BoundingSphere.fromCornerPoints(new Cartesian3(-1.0, -0.0, 0.0), new Cartesian3(1.0, 0.0, 0.0)); expect(sphere).toEqual(new BoundingSphere(Cartesian3.ZERO, 1.0)); diff --git a/Specs/Core/ExtentSpec.js b/Specs/Core/ExtentSpec.js index ed6c4fc1430f..77eef180dc22 100644 --- a/Specs/Core/ExtentSpec.js +++ b/Specs/Core/ExtentSpec.js @@ -341,7 +341,7 @@ defineSuite([ var extent = new Extent(west, south, east, north); var cartesian0 = new Cartesian3(); var results = [cartesian0]; - var returnedResult = extent.subsample(Ellipsoid.WGS84, results); + var returnedResult = extent.subsample(Ellipsoid.WGS84, 0.0, results); expect(results).toBe(returnedResult); expect(results[0]).toBe(cartesian0); expect(returnedResult).toEqual([Ellipsoid.WGS84.cartographicToCartesian(extent.getNorthwest()), @@ -385,6 +385,30 @@ defineSuite([ expect(cartographic5.longitude).toEqualEpsilon(east, CesiumMath.EPSILON16); }); + it('subsample works at a height above the ellipsoid', function() { + var west = 0.1; + var south = -0.3; + var east = 0.2; + var north = -0.4; + var extent = new Extent(west, south, east, north); + var height = 100000.0; + var returnedResult = extent.subsample(Ellipsoid.WGS84, height); + + var nw = extent.getNorthwest(); + nw.height = height; + var ne = extent.getNortheast(); + ne.height = height; + var se = extent.getSoutheast(); + se.height = height; + var sw = extent.getSouthwest(); + sw.height = height; + + expect(returnedResult).toEqual([Ellipsoid.WGS84.cartographicToCartesian(nw), + Ellipsoid.WGS84.cartographicToCartesian(ne), + Ellipsoid.WGS84.cartographicToCartesian(se), + Ellipsoid.WGS84.cartographicToCartesian(sw)]); + }); + it('equalsEpsilon throws with no epsilon', function() { var extent = new Extent(west, south, east, north); var other = new Extent(); From 95fa8a4dd971a599bfd1c559e4aea2a459568326 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Tue, 28 May 2013 13:57:04 -0400 Subject: [PATCH 089/306] Updates based on review. --- CHANGES.md | 3 ++- Source/Core/ExtentGeometry.js | 9 ++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 7b3b31a2cc77..2bd5e1b33b45 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -15,7 +15,8 @@ Beta Releases * Renamed `MeshFilters` to `GeometryFilters`. * Renamed `MeshFilters.toWireframeInPlace` to `GeometryFilters.toWireframe`. * Renamed `ComponentDatatype.*.toTypedArray` to `ComponentDatatype.*.createTypedArray`. - * Replaced `Uniform.getFrameNumber` and `Uniform.getTime` with `Uniform.getFrameState`, which returns the full frame state. + * Replaced `Uniform.getFrameNumber` and `Uniform.getTime` with `Uniform.getFrameState`, which returns the full frame state. + * Removed `Polygon.configureExtent`. * Improved the performance of drawing polygons created with `configureFromPolygonHierarchy`. * Added `GeometryFilters.combine` to combine meshes for better batching. * Added `GeometryFilters.computeNormals` to find the normals of vertices in a mesh. diff --git a/Source/Core/ExtentGeometry.js b/Source/Core/ExtentGeometry.js index ed09bf68da74..0e6391d97d5c 100644 --- a/Source/Core/ExtentGeometry.js +++ b/Source/Core/ExtentGeometry.js @@ -65,7 +65,7 @@ define([ * @param {Ellipsoid} [description.ellipsoid=Ellipsoid.WGS84] The ellipsoid on which the extent lies. * @param {Number} [description.granularity=0.1] The distance, in radians, between each latitude and longitude. Determines the number of positions in the buffer. * @param {Number} [description.surfaceHeight=0.0] The height from the surface of the ellipsoid. - * @param {Number} [description.rotation=0.0] The rotation of the extent in radians. + * @param {Number} [description.rotation=0.0] The rotation of the extent in radians. A positive rotation is counter-clockwise. * * @exception {DeveloperError} description.extent is required and must have north, south, east and west attributes. * @exception {DeveloperError} description.extent.north must be in the interval [-Pi/2, Pi/2]. @@ -206,8 +206,6 @@ define([ if (vertexFormat.normal || vertexFormat.tangent || vertexFormat.binormal) { ellipsoid.geodeticSurfaceNormal(position, normal); - Cartesian3.cross(Cartesian3.UNIT_Z, normal, tangent); - Cartesian3.cross(normal, tangent, binormal); if (vertexFormat.normal) { normals[normalIndex++] = normal.x; @@ -216,12 +214,17 @@ define([ } if (vertexFormat.tangent) { + Cartesian3.cross(Cartesian3.UNIT_Z, normal, tangent); + tangents[tangentIndex++] = tangent.x; tangents[tangentIndex++] = tangent.y; tangents[tangentIndex++] = tangent.z; } if (vertexFormat.binormal) { + Cartesian3.cross(Cartesian3.UNIT_Z, normal, tangent); + Cartesian3.cross(normal, tangent, binormal); + binormals[binormalIndex++] = binormal.x; binormals[binormalIndex++] = binormal.y; binormals[binormalIndex++] = binormal.z; From 68d3a77ffd5e0e215925ad2856db85364e2c7dc5 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Tue, 28 May 2013 16:19:23 -0300 Subject: [PATCH 090/306] Tweak CHANGES.md --- CHANGES.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 2bd5e1b33b45..f513d25ee880 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -17,12 +17,12 @@ Beta Releases * Renamed `ComponentDatatype.*.toTypedArray` to `ComponentDatatype.*.createTypedArray`. * Replaced `Uniform.getFrameNumber` and `Uniform.getTime` with `Uniform.getFrameState`, which returns the full frame state. * Removed `Polygon.configureExtent`. + * Added `height` parameter to `BoundingSphere.fromExtent3D`. + * Added `height` parameter to `Extent.subsample`. * Improved the performance of drawing polygons created with `configureFromPolygonHierarchy`. * Added `GeometryFilters.combine` to combine meshes for better batching. * Added `GeometryFilters.computeNormals` to find the normals of vertices in a mesh. * Added `BoundingSphere.fromEllipsoid`. -* Added `height` parameter to `BoundingSphere.fromExtent3D`. -* Added `height` parameter to `Extent.subsample`. * Added renderer support for `OES_element_index_uint`, which can improve performance by reducing batch sizes. * Added `czm_tangentToEyeSpaceMatrix` built-in GLSL function. * Added `WallGeometry` and `PolygonGeometry`. From 95d2b14d15ce960e94c8b57ec18815dafe15df47 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Tue, 28 May 2013 15:23:19 -0400 Subject: [PATCH 091/306] Make EllipseGeometry expect semi-major and semi-minor axes. Make CircleGeometry expect a radius. Add tests. --- Source/Core/CircleGeometry.js | 9 +++++++-- Source/Core/EllipseGeometry.js | 16 +++++++++++++--- Specs/Core/CircleGeometrySpec.js | 17 +++++++++++++--- Specs/Core/EllipseGeometrySpec.js | 32 +++++++++++++++++++++++++++---- 4 files changed, 62 insertions(+), 12 deletions(-) diff --git a/Source/Core/CircleGeometry.js b/Source/Core/CircleGeometry.js index 63eed95ebc6d..97ea16eef0b6 100644 --- a/Source/Core/CircleGeometry.js +++ b/Source/Core/CircleGeometry.js @@ -20,12 +20,13 @@ define([ * @param {Cartesian3} options.center The ellipse's center point in the fixed frame. * @param {Number} [options.center=1.0] The radius in meters. * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid the ellipse will be on. - * @param {Number} [options.granularity=0.02] The angular distance between points on the circle. + * @param {Number} [options.granularity=0.02] The angular distance between points on the circle in radians. * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed. * @param {Matrix4} [options.modelMatrix] The model matrix for this ellipsoid. * @param {DOC_TBA} [options.pickData] DOC_TBA * * @exception {DeveloperError} center is required. + * @exception {DeveloperError} radius is required. * @exception {DeveloperError} radius must be greater than zero. * @exception {DeveloperError} granularity must be greater than zero. * @@ -40,8 +41,12 @@ define([ */ var CircleGeometry = function(options) { options = defaultValue(options, defaultValue.EMPTY_OBJECT); + var radius = options.radius; + + if (typeof radius === 'undefined') { + throw new DeveloperError('radius is required.'); + } - var radius = defaultValue(options.radius, 1.0); if (radius <= 0.0) { throw new DeveloperError('radius must be greater than zero.'); } diff --git a/Source/Core/EllipseGeometry.js b/Source/Core/EllipseGeometry.js index 9e1c8b8a5636..ed33ca0f55d0 100644 --- a/Source/Core/EllipseGeometry.js +++ b/Source/Core/EllipseGeometry.js @@ -53,12 +53,14 @@ define([ * @param {Number} [options.semiMajorAxis=1.0] The length of the ellipse's semi-major axis in meters. * @param {Number} [options.semiMinorAxis=1.0] The length of the ellipse's semi-minor axis in meters. * @param {Number} [options.bearing=0.0] The angle from north (clockwise) in radians. The default is zero. - * @param {Number} [options.granularity=0.02] The angular distance between points on the circle. + * @param {Number} [options.granularity=0.02] The angular distance between points on the circle in radians. * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed. * @param {Matrix4} [options.modelMatrix] The model matrix for this ellipsoid. * @param {DOC_TBA} [options.pickData] DOC_TBA * * @exception {DeveloperError} center is required. + * @exception {DeveloperError} semiMajorAxis is required. + * @exception {DeveloperError} semiMinorAxis is required. * @exception {DeveloperError} semiMajorAxis and semiMinorAxis must be greater than zero. * @exception {DeveloperError} granularity must be greater than zero. * @@ -76,10 +78,10 @@ define([ var EllipseGeometry = function(options) { options = defaultValue(options, defaultValue.EMPTY_OBJECT); var center = options.center; + var semiMajorAxis = options.semiMajorAxis; + var semiMinorAxis = options.semiMinorAxis; var ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84); - var semiMajorAxis = defaultValue(options.semiMajorAxis, 1.0); - var semiMinorAxis = defaultValue(options.semiMinorAxis, 1.0); var bearing = defaultValue(options.bearing, 0.0); var granularity = defaultValue(options.granularity, 0.02); @@ -87,6 +89,14 @@ define([ throw new DeveloperError('center is required.'); } + if (typeof semiMajorAxis === 'undefined') { + throw new DeveloperError('semiMajorAxis is required.'); + } + + if (typeof semiMinorAxis === 'undefined') { + throw new DeveloperError('semiMinorAxis is required.'); + } + if (semiMajorAxis <= 0.0 || semiMinorAxis <= 0.0) { throw new DeveloperError('Semi-major and semi-minor axes must be greater than zero.'); } diff --git a/Specs/Core/CircleGeometrySpec.js b/Specs/Core/CircleGeometrySpec.js index 1ef1d6e69ba4..0043d4ac9b58 100644 --- a/Specs/Core/CircleGeometrySpec.js +++ b/Specs/Core/CircleGeometrySpec.js @@ -16,14 +16,24 @@ defineSuite([ it('throws without a center', function() { expect(function() { - return new CircleGeometry({}); + return new CircleGeometry({ + radius : 1.0 + }); + }).toThrow(); + }); + + it('throws without a radius', function() { + expect(function() { + return new CircleGeometry({ + center : Ellipsoid.WGS84.cartographicToCartesian(new Cartographic()) + }); }).toThrow(); }); it('throws with a negative radius', function() { expect(function() { return new CircleGeometry({ - center : Cartesian3.UNIT_X, + center : Ellipsoid.WGS84.cartographicToCartesian(new Cartographic()), radius : -1.0 }); }).toThrow(); @@ -32,7 +42,8 @@ defineSuite([ it('throws with a negative granularity', function() { expect(function() { return new CircleGeometry({ - center : Cartesian3.UNIT_X, + center : Ellipsoid.WGS84.cartographicToCartesian(new Cartographic()), + radius : 1.0, granularity : -1.0 }); }).toThrow(); diff --git a/Specs/Core/EllipseGeometrySpec.js b/Specs/Core/EllipseGeometrySpec.js index 2dc773d912b5..7e0bcc1d2949 100644 --- a/Specs/Core/EllipseGeometrySpec.js +++ b/Specs/Core/EllipseGeometrySpec.js @@ -16,15 +16,37 @@ defineSuite([ it('throws without a center', function() { expect(function() { - return new EllipseGeometry({}); + return new EllipseGeometry({ + semiMajorAxis : 1.0, + semiMinorAxis : 1.0 + }); + }).toThrow(); + }); + + it('throws without a semiMajorAxis', function() { + expect(function() { + return new EllipseGeometry({ + center : Ellipsoid.WGS84.cartographicToCartesian(new Cartographic()), + semiMinorAxis : 1.0 + }); + }).toThrow(); + }); + + it('throws without a semiMinorAxis', function() { + expect(function() { + return new EllipseGeometry({ + center : Ellipsoid.WGS84.cartographicToCartesian(new Cartographic()), + semiMajorAxis : 1.0 + }); }).toThrow(); }); it('throws with a negative axis', function() { expect(function() { return new EllipseGeometry({ - center : Cartesian3.UNIT_X, - semiMajorAxis : -1.0 + center : Ellipsoid.WGS84.cartographicToCartesian(new Cartographic()), + semiMajorAxis : 1.0, + semiMinorAxis : -1.0 }); }).toThrow(); }); @@ -32,7 +54,9 @@ defineSuite([ it('throws with a negative granularity', function() { expect(function() { return new EllipseGeometry({ - center : Cartesian3.UNIT_X, + center : Ellipsoid.WGS84.cartographicToCartesian(new Cartographic()), + semiMajorAxis : 1.0, + semiMinorAxis : 1.0, granularity : -1.0 }); }).toThrow(); From f0cd7dd686dc3e453de3699b1c21f5d4bfad43b6 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Tue, 28 May 2013 15:56:07 -0400 Subject: [PATCH 092/306] Add height to ellipse and circle geometry. --- Apps/CesiumViewer/CesiumViewer.js | 3 ++- Source/Core/CircleGeometry.js | 7 ++++--- Source/Core/EllipseGeometry.js | 12 ++++++++---- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index 7686288e3a34..fb8798a6bbbf 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -106,7 +106,8 @@ define([ center : ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-100, 20)), semiMinorAxis : 500000.0, semiMajorAxis : 1000000.0, - bearing : 0.0, + bearing : CesiumMath.PI_OVER_FOUR, + height : 100000.0, pickData : 'mesh4' }); diff --git a/Source/Core/CircleGeometry.js b/Source/Core/CircleGeometry.js index 97ea16eef0b6..e4bc0be781d6 100644 --- a/Source/Core/CircleGeometry.js +++ b/Source/Core/CircleGeometry.js @@ -17,9 +17,10 @@ define([ * @alias EllipseGeometry * @constructor * - * @param {Cartesian3} options.center The ellipse's center point in the fixed frame. - * @param {Number} [options.center=1.0] The radius in meters. - * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid the ellipse will be on. + * @param {Cartesian3} options.center The circle's center point in the fixed frame. + * @param {Number} options.radius The radius in meters. + * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid the circle will be on. + * @param {Number} [options.height=0.0] The height above the ellipsoid. * @param {Number} [options.granularity=0.02] The angular distance between points on the circle in radians. * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed. * @param {Matrix4} [options.modelMatrix] The model matrix for this ellipsoid. diff --git a/Source/Core/EllipseGeometry.js b/Source/Core/EllipseGeometry.js index ed33ca0f55d0..8b273da0b10a 100644 --- a/Source/Core/EllipseGeometry.js +++ b/Source/Core/EllipseGeometry.js @@ -49,11 +49,12 @@ define([ * @constructor * * @param {Cartesian3} options.center The ellipse's center point in the fixed frame. + * @param {Number} options.semiMajorAxis The length of the ellipse's semi-major axis in meters. + * @param {Number} options.semiMinorAxis The length of the ellipse's semi-minor axis in meters. * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid the ellipse will be on. - * @param {Number} [options.semiMajorAxis=1.0] The length of the ellipse's semi-major axis in meters. - * @param {Number} [options.semiMinorAxis=1.0] The length of the ellipse's semi-minor axis in meters. + * @param {Number} [options.height=0.0] The height above the ellipsoid. * @param {Number} [options.bearing=0.0] The angle from north (clockwise) in radians. The default is zero. - * @param {Number} [options.granularity=0.02] The angular distance between points on the circle in radians. + * @param {Number} [options.granularity=0.02] The angular distance between points on the ellipse in radians. * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed. * @param {Matrix4} [options.modelMatrix] The model matrix for this ellipsoid. * @param {DOC_TBA} [options.pickData] DOC_TBA @@ -83,6 +84,7 @@ define([ var ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84); var bearing = defaultValue(options.bearing, 0.0); + var height = defaultValue(options.height, 0.0); var granularity = defaultValue(options.granularity, 0.02); if (typeof center === 'undefined') { @@ -150,7 +152,7 @@ define([ var positions = new Array(size * 3); positions[0] = semiMajorAxis; positions[1] = 0.0; - positions[2] = 0.0; + positions[2] = height; var positionIndex = 3; var position = scratchCartesian1; @@ -162,11 +164,13 @@ define([ // Compute the position on the ellipse in the first quadrant. position.x = Math.cos(angle) * semiMajorAxis; position.y = Math.sin(angle) * semiMinorAxis; + position.z = height; // Reflect the position across the x axis for a point on the ellipse // in the fourth quadrant. reflectedPosition.x = position.x; reflectedPosition.y = -position.y; + reflectedPosition.z = position.z; positions[positionIndex++] = position.x; positions[positionIndex++] = position.y; From 2344145c90b46caacd65dc3a78581a5618b936ea Mon Sep 17 00:00:00 2001 From: hpinkos Date: Tue, 28 May 2013 16:08:40 -0400 Subject: [PATCH 093/306] minor fixes --- Source/Core/GeometryFilters.js | 18 ++++++++---------- Specs/Core/GeometryFiltersSpec.js | 10 +++++----- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/Source/Core/GeometryFilters.js b/Source/Core/GeometryFilters.js index c174dae8702e..22c2c359c1c9 100644 --- a/Source/Core/GeometryFilters.js +++ b/Source/Core/GeometryFilters.js @@ -994,6 +994,8 @@ define([ * Computes the tangent and binormal of all vertices in a geometry * This assumes a counter-clockwise vertex winding order. * + * Based on: Lengyel, Eric. “Computing Tangent Space Basis Vectors for an Arbitrary Mesh”. Terathon Software 3D Graphics Library, 2001. http://www.terathon.com/code/tangent.html + * * @param {Geometry} geometry The geometry for which to calculate tangents and binormals, which is modified in place. * @param {Object} geometry.attributes.position The vertices of the geometry * @param {Object} geometry.attributes.normal The normals of the vertices @@ -1066,7 +1068,9 @@ define([ tan1[i] = 0; } - var i03, i13, i23; + var i03; + var i13; + var i23; for (i = 0; i < numIndices; i+=3) { var i0 = indices[i]; var i1 = indices[i+1]; @@ -1111,21 +1115,15 @@ define([ i13 = i03+1; i23 = i03+2; - var n = normalScratch; - n.x = normals[i03]; - n.y = normals[i13]; - n.z = normals[i23]; - var t = tScratch; - t.x = tan1[i03]; - t.y = tan1[i13]; - t.z = tan1[i23]; + var n = Cartesian3.fromArray(normals.slice(i03, i03 + 3), 0, normalScratch); + var t = Cartesian3.fromArray(tan1.slice(i03, i03 + 3), 0, tScratch); var scalar = n.dot(t); n.multiplyByScalar(scalar, normalScale); t.subtract(normalScale, t).normalize(t); tangentValues[i03] = t.x; tangentValues[i13] = t.y; tangentValues[i23] = t.z; - t.cross(n, t).normalize(t); + n.cross(t, t).normalize(t); binormalValues[i03] = t.x; binormalValues[i13] = t.y; binormalValues[i23] = t.z; diff --git a/Specs/Core/GeometryFiltersSpec.js b/Specs/Core/GeometryFiltersSpec.js index 58c2e8b3342b..4e8ee68db287 100644 --- a/Specs/Core/GeometryFiltersSpec.js +++ b/Specs/Core/GeometryFiltersSpec.js @@ -1108,7 +1108,7 @@ defineSuite([ mesh = GeometryFilters.computeTangentAndBinormal(mesh); expect(mesh.attributes.tangent.values).toEqual([1, 0, 0, 1, 0, 0, 1, 0, 0]); - expect(mesh.attributes.binormal.values).toEqual([0, -1, 0, 0, -1, 0, 0, -1, 0]); + expect(mesh.attributes.binormal.values).toEqual([0, 1, 0, 0, 1, 0, 0, 1, 0]); }); it('GeometryFilters.computeTangentAndBinormal computes tangent and binormal for two triangles', function() { @@ -1141,10 +1141,10 @@ defineSuite([ 0, 1, 0, 0, 1, 0, -0.5773502691896258, 0.5773502691896258, 0.5773502691896258], CesiumMath.EPSILON8); - expect(mesh.attributes.binormal.values).toEqualEpsilon([0, -1, 0, - 1, 0, 0, - 1, 0, 0, - 0.4082482904638631, 0.8164965809277261, -0.4082482904638631], CesiumMath.EPSILON8); + expect(mesh.attributes.binormal.values).toEqualEpsilon([0, 1, 0, + -1, 0, 0, + -1, 0, 0, + -0.4082482904638631, -0.8164965809277261, 0.4082482904638631], CesiumMath.EPSILON8); }); it ('GeometryFilters.computeTangentAndBinormal computes tangent and binormal for an EllipsoidGeometry', function() { From 29bed1bf2cb280d4da91e1ac8f89a815d7447e53 Mon Sep 17 00:00:00 2001 From: hpinkos Date: Tue, 28 May 2013 17:25:59 -0400 Subject: [PATCH 094/306] correct call to cartesian3.fromarray --- Source/Core/GeometryFilters.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Core/GeometryFilters.js b/Source/Core/GeometryFilters.js index 22c2c359c1c9..539b095bf52b 100644 --- a/Source/Core/GeometryFilters.js +++ b/Source/Core/GeometryFilters.js @@ -1115,8 +1115,8 @@ define([ i13 = i03+1; i23 = i03+2; - var n = Cartesian3.fromArray(normals.slice(i03, i03 + 3), 0, normalScratch); - var t = Cartesian3.fromArray(tan1.slice(i03, i03 + 3), 0, tScratch); + var n = Cartesian3.fromArray(normals, i03, normalScratch); + var t = Cartesian3.fromArray(tan1, i03, tScratch); var scalar = n.dot(t); n.multiplyByScalar(scalar, normalScale); t.subtract(normalScale, t).normalize(t); From 9488ccc474e4b15a2af43e78c0dbc3d0e997faa5 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 30 May 2013 15:56:42 -0400 Subject: [PATCH 095/306] Start tessellating ellipse on an ellipsoid instead of on a plane. --- Apps/CesiumViewer/CesiumViewer.js | 6 +- Source/Core/EllipseGeometry.js | 183 ++++++++++++++++++------------ Source/Scene/Appearance.js | 2 +- 3 files changed, 117 insertions(+), 74 deletions(-) diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index fb8798a6bbbf..67dbc4d05479 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -106,8 +106,10 @@ define([ center : ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-100, 20)), semiMinorAxis : 500000.0, semiMajorAxis : 1000000.0, - bearing : CesiumMath.PI_OVER_FOUR, - height : 100000.0, + //bearing : CesiumMath.PI_OVER_FOUR, + height : 1000000.0, + //granularity : 0.50, + //granularity : CesiumMath.PI_OVER_FOUR, pickData : 'mesh4' }); diff --git a/Source/Core/EllipseGeometry.js b/Source/Core/EllipseGeometry.js index 8b273da0b10a..fee0c2f00d97 100644 --- a/Source/Core/EllipseGeometry.js +++ b/Source/Core/EllipseGeometry.js @@ -13,8 +13,10 @@ define([ './GeometryIndices', './Math', './Matrix2', + './Matrix3', './Matrix4', './PrimitiveType', + './Quaternion', './VertexFormat' ], function( defaultValue, @@ -30,11 +32,23 @@ define([ GeometryIndices, CesiumMath, Matrix2, + Matrix3, Matrix4, PrimitiveType, + Quaternion, VertexFormat) { "use strict"; + function reflect(position, center, unitVector, result) { + var toCenter = Cartesian3.subtract(position, center); + Cartesian3.multiplyByScalar(unitVector, Cartesian3.dot(toCenter, unitVector), result); + var perp = Cartesian3.subtract(toCenter, result); + Cartesian3.negate(perp, perp); + Cartesian3.add(perp, result, result); + Cartesian3.add(center, result, result); + return result; + } + var scratchCartesian1 = new Cartesian3(); var scratchCartesian2 = new Cartesian3(); var scratchCartesian3 = new Cartesian3(); @@ -115,9 +129,24 @@ define([ var vertexFormat = defaultValue(options.vertexFormat, VertexFormat.DEFAULT); + var MAX_ANOMALY_LIMIT = 2.31; + + //var aSqr = semiMajorAxis * semiMajorAxis; + //var bSqr = semiMinorAxis * semiMinorAxis; + var aSqr = semiMinorAxis * semiMinorAxis; + var bSqr = semiMajorAxis * semiMajorAxis; + var ab = semiMajorAxis * semiMinorAxis; + + var mag = center.magnitude(); + + var unitPos = Cartesian3.normalize(center); + var eastVec = Cartesian3.cross(Cartesian3.UNIT_Z, center); + Cartesian3.normalize(eastVec, eastVec); + var northVec = Cartesian3.cross(unitPos, eastVec); + // The number of points in the first quadrant - var numPts = Math.ceil(CesiumMath.PI_OVER_TWO / granularity) + 1; - var deltaTheta = CesiumMath.PI_OVER_TWO / (numPts - 1); + var numPts = 1 + Math.ceil(CesiumMath.PI_OVER_TWO / granularity); + var deltaTheta = MAX_ANOMALY_LIMIT / (numPts - 1); // If the number of points were three, the ellipse // would be tessellated like below: @@ -134,51 +163,63 @@ define([ // Notice each vertical column contains an odd number of positions. // The sum of the first n odd numbers is n^2. Double it for the number of points // for the whole ellipse - var size = 2 * numPts * numPts; - - // If the ellipsoid contains points on the y axis, remove on of the - // central columns of positions because they would be duplicated. - var reachedPiOverTwo = false; - if (deltaTheta * (numPts - 1) > CesiumMath.PI_OVER_TWO) { - size -= 2 * numPts - 1; - reachedPiOverTwo = true; - } - - var i; - var j; - var numInterior; + //var size = 2 * numPts * numPts; // Compute the points in the positive x half-space in 2D. - var positions = new Array(size * 3); + /*var positions = new Array(size * 3); positions[0] = semiMajorAxis; positions[1] = 0.0; positions[2] = height; var positionIndex = 3; + */ + + var rotation = Matrix3.fromQuaternion(Quaternion.fromAxisAngle(unitPos, bearing)); + var rotatedNorthVec = Matrix3.multiplyByVector(rotation, northVec); + var rotatedEastVec = Matrix3.multiplyByVector(rotation, eastVec); + Cartesian3.normalize(rotatedNorthVec, rotatedNorthVec); + Cartesian3.normalize(rotatedEastVec, rotatedEastVec); var position = scratchCartesian1; var reflectedPosition = scratchCartesian2; - for (i = 1; i < numPts; ++i) { - var angle = Math.min(i * deltaTheta, CesiumMath.PI_OVER_TWO); + var positions = []; + var positionIndex = 0; + + var i; + var j; + var numInterior; + var theta; + + for (i = 0, theta = CesiumMath.PI_OVER_TWO; i < numPts && theta > 0; ++i, theta -= deltaTheta) { + var azimuth = theta + bearing; + var rotAxis = Cartesian3.multiplyByScalar(eastVec, Math.cos(azimuth)); + var tempVec = Cartesian3.multiplyByScalar(northVec, Math.sin(azimuth)); + Cartesian3.add(rotAxis, tempVec, rotAxis); - // Compute the position on the ellipse in the first quadrant. - position.x = Math.cos(angle) * semiMajorAxis; - position.y = Math.sin(angle) * semiMinorAxis; - position.z = height; + var cosThetaSquared = Math.cos(theta); + cosThetaSquared = cosThetaSquared * cosThetaSquared; - // Reflect the position across the x axis for a point on the ellipse - // in the fourth quadrant. - reflectedPosition.x = position.x; - reflectedPosition.y = -position.y; - reflectedPosition.z = position.z; + var sinThetaSquared = Math.sin(theta); + sinThetaSquared = sinThetaSquared * sinThetaSquared; + + var radius = ab / Math.sqrt(bSqr * cosThetaSquared + aSqr * sinThetaSquared); + var angle = radius / mag; + + // Create the quaternion to rotate the position vector to the boundary of the ellipse. + var unitQuat = Quaternion.fromAxisAngle(rotAxis, angle); + var rotMtx = Matrix3.fromQuaternion(unitQuat); + + Matrix3.multiplyByVector(rotMtx, unitPos, position); + Cartesian3.normalize(position, position); + Cartesian3.multiplyByScalar(position, mag, position); + + reflect(position, center, rotatedEastVec, reflectedPosition); positions[positionIndex++] = position.x; positions[positionIndex++] = position.y; positions[positionIndex++] = position.z; - // Compute the points on the interior of the ellipse, on the line - // through the points in the first and fourth quadrants - numInterior = 2 * i + 1; + numInterior = 2 * i + 2; for (j = 1; j < numInterior - 1; ++j) { var t = j / (numInterior - 1); var interiorPosition = Cartesian3.lerp(position, reflectedPosition, t, scratchCartesian3); @@ -192,27 +233,26 @@ define([ positions[positionIndex++] = reflectedPosition.z; } - var reverseIndex; - if (reachedPiOverTwo) { - i = numPts - 1; - reverseIndex = positionIndex - (numPts * 2 - 1) * 3; - } else { - i = numPts; - reverseIndex = positionIndex; - } + numPts = i; + + var reverseIndex = positionIndex; // Reflect the points across the y axis to get the other half of the ellipsoid. - for (; i > 0; --i) { - numInterior = 2 * i - 1; + for (i = numPts; i > 0; --i) { + numInterior = 2 * i; reverseIndex -= numInterior * 3; for (j = 0; j < numInterior; ++j) { - var index = reverseIndex + j * 3; - positions[positionIndex++] = -positions[index]; - positions[positionIndex++] = positions[index + 1]; - positions[positionIndex++] = positions[index + 2]; + var index = reverseIndex + j * 3; + Cartesian3.fromArray(positions, index, position); + reflect(position, center, rotatedNorthVec, reflectedPosition); + + positions[positionIndex++] = reflectedPosition.x; + positions[positionIndex++] = reflectedPosition.y; + positions[positionIndex++] = reflectedPosition.z; } } + /* var textureCoordinates = (vertexFormat.st) ? new Array(size * 2) : undefined; var normals = (vertexFormat.normal) ? new Array(size * 3) : undefined; var tangents = (vertexFormat.tangent) ? new Array(size * 3) : undefined; @@ -230,11 +270,15 @@ define([ var normal; var tangent; var binormal; + */ var length = positions.length; for (i = 0; i < length; i += 3) { position = Cartesian3.fromArray(positions, i, scratchCartesian2); + ellipsoid.scaleToGeodeticSurface(position, position); + Cartesian3.add(position, Cartesian3.multiplyByScalar(ellipsoid.geodeticSurfaceNormal(position), height), position); + /* if (vertexFormat.st) { textureCoordinates[textureCoordIndex++] = (position.x + semiMajorAxis) / (2.0 * semiMajorAxis); textureCoordinates[textureCoordIndex++] = (position.y + semiMinorAxis) / (2.0 * semiMinorAxis); @@ -245,6 +289,7 @@ define([ var unprojected = projection.unproject(position, scratchCartographic); ellipsoid.cartographicToCartesian(unprojected, position); + */ if (vertexFormat.position) { positions[i] = position.x; @@ -252,6 +297,7 @@ define([ positions[i + 2] = position.z; } + /* if (vertexFormat.normal) { normal = ellipsoid.geodeticSurfaceNormal(position, scratchCartesian3); @@ -278,6 +324,7 @@ define([ binormals[i + 1] = binormal.y; binormals[i + 2] = binormal.z; } + */ } var attributes = {}; @@ -290,6 +337,7 @@ define([ }); } + /* if (vertexFormat.st) { attributes.st = new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, @@ -321,6 +369,7 @@ define([ values : binormals }); } + */ // The number of triangles in the ellipse on the positive x half-space is: // @@ -332,27 +381,21 @@ define([ // // numTriangles = 2 * (numInteriorTriangles + numExteriorTriangles) // numIndices = 3 * numTriangles - - var indicesSize = 12.0 * numPts * numPts; - if (reachedPiOverTwo) { - indicesSize += 12.0 * (numPts - 1.0); - } - - var indices = new Array(indicesSize); + //var indices = new Array(indicesSize); + var indices = []; var indicesIndex = 0; var prevIndex; // Indices for positive x half-space - for (i = 0; i < numPts - 1; ++i) { - positionIndex = i + 1; - positionIndex *= positionIndex; - prevIndex = i * i; + for (i = 1; i < numPts; ++i) { + positionIndex = i * (i + 1); + prevIndex = (i - 1) * i; indices[indicesIndex++] = positionIndex++; indices[indicesIndex++] = positionIndex; indices[indicesIndex++] = prevIndex; - numInterior = 2 * i + 1; + numInterior = 2 * i; for (j = 0; j < numInterior - 1; ++j) { indices[indicesIndex++] = prevIndex++; indices[indicesIndex++] = positionIndex; @@ -368,20 +411,18 @@ define([ indices[indicesIndex++] = prevIndex; } - // Indices for central column of triangles (if there is one) - if (!reachedPiOverTwo) { - numInterior = numPts * 2 - 1; - ++positionIndex; - ++prevIndex; - for (i = 0; i < numInterior - 1; ++i) { - indices[indicesIndex++] = prevIndex++; - indices[indicesIndex++] = positionIndex; - indices[indicesIndex++] = prevIndex; + // Indices for central column of triangles + numInterior = numPts * 2; + ++positionIndex; + ++prevIndex; + for (i = 0; i < numInterior - 1; ++i) { + indices[indicesIndex++] = prevIndex++; + indices[indicesIndex++] = positionIndex; + indices[indicesIndex++] = prevIndex; - indices[indicesIndex++] = positionIndex++; - indices[indicesIndex++] = positionIndex; - indices[indicesIndex++] = prevIndex; - } + indices[indicesIndex++] = positionIndex++; + indices[indicesIndex++] = positionIndex; + indices[indicesIndex++] = prevIndex; } // Reverse the process creating indices for the ellipse on the positive x half-space @@ -393,7 +434,7 @@ define([ indices[indicesIndex++] = positionIndex; indices[indicesIndex++] = prevIndex; - numInterior = 2 * (i - 1) + 1; + numInterior = 2 * i; for (j = 0; j < numInterior - 1; ++j) { indices[indicesIndex++] = prevIndex++; indices[indicesIndex++] = positionIndex; @@ -409,7 +450,7 @@ define([ indices[indicesIndex++] = prevIndex++; } - indices.length = indicesIndex; + //indices.length = indicesIndex; /** * An object containing {@link GeometryAttribute} properties named after each of the diff --git a/Source/Scene/Appearance.js b/Source/Scene/Appearance.js index ae6f1a5aab18..0247c56ec88a 100644 --- a/Source/Scene/Appearance.js +++ b/Source/Scene/Appearance.js @@ -60,7 +60,7 @@ define([ Appearance.CLOSED_TRANSLUCENT = freezeObject(new Appearance({ renderState : { cull : { - enabled : true, + //enabled : true, face : CullFace.BACK }, depthTest : { From e39704c42891c0524aa8766499c3c7a44fe420b5 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 30 May 2013 16:29:01 -0400 Subject: [PATCH 096/306] Clean up comments and recalculate the number of positions and indices up front (conservative estimate). --- Source/Core/EllipseGeometry.js | 59 +++++++++++++++------------------- 1 file changed, 26 insertions(+), 33 deletions(-) diff --git a/Source/Core/EllipseGeometry.js b/Source/Core/EllipseGeometry.js index fee0c2f00d97..db3e79d8f227 100644 --- a/Source/Core/EllipseGeometry.js +++ b/Source/Core/EllipseGeometry.js @@ -131,8 +131,6 @@ define([ var MAX_ANOMALY_LIMIT = 2.31; - //var aSqr = semiMajorAxis * semiMajorAxis; - //var bSqr = semiMinorAxis * semiMinorAxis; var aSqr = semiMinorAxis * semiMinorAxis; var bSqr = semiMajorAxis * semiMajorAxis; var ab = semiMajorAxis * semiMinorAxis; @@ -156,22 +154,20 @@ define([ // *---*---*---* // / | \ | \ | \ | \ // *---*---*---*---*---* + // | \ | \ | \ | \ | \ | + // *---*---*---*---*---* // \ | \ | \ | \ | / // *---*---*---* // \ | \ | / // *---* - // Notice each vertical column contains an odd number of positions. - // The sum of the first n odd numbers is n^2. Double it for the number of points - // for the whole ellipse - //var size = 2 * numPts * numPts; - - // Compute the points in the positive x half-space in 2D. - /*var positions = new Array(size * 3); - positions[0] = semiMajorAxis; - positions[1] = 0.0; - positions[2] = height; - var positionIndex = 3; - */ + // Notice each vertical column contains an even number of positions. + // The sum of the first n even numbers is n * (n + 1). Double it for the number of points + // for the whole ellipse. Note: this is just an estimate and may actually be less depending + // on the number of iterations before the angle reaches pi/2. + var size = 2 * numPts * (numPts + 1); + + var positions = new Array(size * 3); + var positionIndex = 0; var rotation = Matrix3.fromQuaternion(Quaternion.fromAxisAngle(unitPos, bearing)); var rotatedNorthVec = Matrix3.multiplyByVector(rotation, northVec); @@ -182,9 +178,6 @@ define([ var position = scratchCartesian1; var reflectedPosition = scratchCartesian2; - var positions = []; - var positionIndex = 0; - var i; var j; var numInterior; @@ -234,10 +227,9 @@ define([ } numPts = i; - var reverseIndex = positionIndex; - // Reflect the points across the y axis to get the other half of the ellipsoid. + // Reflect the points across the north axis to get the other half of the ellipsoid. for (i = numPts; i > 0; --i) { numInterior = 2 * i; reverseIndex -= numInterior * 3; @@ -252,6 +244,9 @@ define([ } } + // The original length may have been an over-estimate + positions.length = positionIndex; + /* var textureCoordinates = (vertexFormat.st) ? new Array(size * 2) : undefined; var normals = (vertexFormat.normal) ? new Array(size * 3) : undefined; @@ -371,22 +366,21 @@ define([ } */ - // The number of triangles in the ellipse on the positive x half-space is: - // - // numInteriorTriangles = 4 + 8 + 12 + ... = 4 + (4 + 4) + (4 + 4 + 4) + ... = 4 * (1 + 2 + 3 + ...) - // = 4 * ((n * ( n + 1)) / 2) - // numExteriorTriangles = 2 * n + // The number of triangles in the ellipse on the positive x half-space and for + // the column of triangles in the middle is: // - // Substitute (numPts - 1.0) for n above and then: + // numTriangles = 4 + 8 + 12 + ... = 4 + (4 + 4) + (4 + 4 + 4) + ... = 4 * (1 + 2 + 3 + ...) + // = 4 * ((n * ( n + 1)) / 2) + // numColumnTriangles = 2 * 2 * n + // total = 2 * numTrangles + numcolumnTriangles // - // numTriangles = 2 * (numInteriorTriangles + numExteriorTriangles) - // numIndices = 3 * numTriangles - //var indices = new Array(indicesSize); - var indices = []; + // Substitute (numPts - 1.0) for n above + var indicesSize = 2 * numPts * (numPts + 1); + var indices = new Array(indicesSize); var indicesIndex = 0; var prevIndex; - // Indices for positive x half-space + // Indices triangles to the 'left' of the north vector for (i = 1; i < numPts; ++i) { positionIndex = i * (i + 1); prevIndex = (i - 1) * i; @@ -425,8 +419,7 @@ define([ indices[indicesIndex++] = prevIndex; } - // Reverse the process creating indices for the ellipse on the positive x half-space - // to create the part of the ellipse reflected on the y axis. + // Reverse the process creating indices to the 'right' of the north vector ++prevIndex; ++positionIndex; for (i = numPts - 1; i > 0; --i) { @@ -450,7 +443,7 @@ define([ indices[indicesIndex++] = prevIndex++; } - //indices.length = indicesIndex; + indices.length = indicesIndex; /** * An object containing {@link GeometryAttribute} properties named after each of the From 7d590e8a3a157db139494ead4c3e4494d7718db8 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 30 May 2013 16:37:06 -0400 Subject: [PATCH 097/306] Re-add normals, tangents, binormals, and texture coordinates. --- Apps/CesiumViewer/CesiumViewer.js | 2 -- Source/Core/EllipseGeometry.js | 32 ++++++++----------------------- 2 files changed, 8 insertions(+), 26 deletions(-) diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index 67dbc4d05479..44563567cd3d 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -108,8 +108,6 @@ define([ semiMajorAxis : 1000000.0, //bearing : CesiumMath.PI_OVER_FOUR, height : 1000000.0, - //granularity : 0.50, - //granularity : CesiumMath.PI_OVER_FOUR, pickData : 'mesh4' }); diff --git a/Source/Core/EllipseGeometry.js b/Source/Core/EllipseGeometry.js index db3e79d8f227..b466f3c2957e 100644 --- a/Source/Core/EllipseGeometry.js +++ b/Source/Core/EllipseGeometry.js @@ -246,8 +246,8 @@ define([ // The original length may have been an over-estimate positions.length = positionIndex; + size = positions.length / 3; - /* var textureCoordinates = (vertexFormat.st) ? new Array(size * 2) : undefined; var normals = (vertexFormat.normal) ? new Array(size * 3) : undefined; var tangents = (vertexFormat.tangent) ? new Array(size * 3) : undefined; @@ -255,36 +255,24 @@ define([ var textureCoordIndex = 0; - // Rotate/translate the positions in the xy-plane and un-project to the ellipsoid in 3D. - // Compute the texture coordinates, normals, tangents, and binormals at the same times. - var projection = new GeographicProjection(ellipsoid); - var centerCart = ellipsoid.cartesianToCartographic(center, scratchCartographic); - var projectedCenter = projection.project(centerCart, scratchCartesian1); - var rotation = Matrix2.fromRotation(bearing, scratchMatrix2); - + // Raise positions to a height above the ellipsoid and compute the + // texture coordinates, normals, tangents, and binormals. var normal; var tangent; var binormal; - */ var length = positions.length; for (i = 0; i < length; i += 3) { position = Cartesian3.fromArray(positions, i, scratchCartesian2); - ellipsoid.scaleToGeodeticSurface(position, position); - Cartesian3.add(position, Cartesian3.multiplyByScalar(ellipsoid.geodeticSurfaceNormal(position), height), position); - /* if (vertexFormat.st) { - textureCoordinates[textureCoordIndex++] = (position.x + semiMajorAxis) / (2.0 * semiMajorAxis); - textureCoordinates[textureCoordIndex++] = (position.y + semiMinorAxis) / (2.0 * semiMinorAxis); + var relativeToCenter = Cartesian3.subtract(position, center); + textureCoordinates[textureCoordIndex++] = (relativeToCenter.x + semiMajorAxis) / (2.0 * semiMajorAxis); + textureCoordinates[textureCoordIndex++] = (relativeToCenter.y + semiMinorAxis) / (2.0 * semiMinorAxis); } - Matrix2.multiplyByVector(rotation, position, position); - Cartesian2.add(projectedCenter, position, position); - - var unprojected = projection.unproject(position, scratchCartographic); - ellipsoid.cartographicToCartesian(unprojected, position); - */ + ellipsoid.scaleToGeodeticSurface(position, position); + Cartesian3.add(position, Cartesian3.multiplyByScalar(ellipsoid.geodeticSurfaceNormal(position), height), position); if (vertexFormat.position) { positions[i] = position.x; @@ -292,7 +280,6 @@ define([ positions[i + 2] = position.z; } - /* if (vertexFormat.normal) { normal = ellipsoid.geodeticSurfaceNormal(position, scratchCartesian3); @@ -319,7 +306,6 @@ define([ binormals[i + 1] = binormal.y; binormals[i + 2] = binormal.z; } - */ } var attributes = {}; @@ -332,7 +318,6 @@ define([ }); } - /* if (vertexFormat.st) { attributes.st = new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, @@ -364,7 +349,6 @@ define([ values : binormals }); } - */ // The number of triangles in the ellipse on the positive x half-space and for // the column of triangles in the middle is: From 2854b12529624377f596cb94bedd11cb19d7468a Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 30 May 2013 19:40:11 -0400 Subject: [PATCH 098/306] Fix problems with reflecting points computed on the ellipsoid. --- Apps/CesiumViewer/CesiumViewer.js | 2 +- Source/Core/EllipseGeometry.js | 96 ++++++++++++++++--------------- 2 files changed, 50 insertions(+), 48 deletions(-) diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index 44563567cd3d..d768a9126c36 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -106,7 +106,7 @@ define([ center : ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-100, 20)), semiMinorAxis : 500000.0, semiMajorAxis : 1000000.0, - //bearing : CesiumMath.PI_OVER_FOUR, + bearing : CesiumMath.PI_OVER_FOUR, height : 1000000.0, pickData : 'mesh4' }); diff --git a/Source/Core/EllipseGeometry.js b/Source/Core/EllipseGeometry.js index b466f3c2957e..52b00b34ad34 100644 --- a/Source/Core/EllipseGeometry.js +++ b/Source/Core/EllipseGeometry.js @@ -39,13 +39,28 @@ define([ VertexFormat) { "use strict"; - function reflect(position, center, unitVector, result) { - var toCenter = Cartesian3.subtract(position, center); - Cartesian3.multiplyByScalar(unitVector, Cartesian3.dot(toCenter, unitVector), result); - var perp = Cartesian3.subtract(toCenter, result); - Cartesian3.negate(perp, perp); - Cartesian3.add(perp, result, result); - Cartesian3.add(center, result, result); + function pointOnEllipsoid(theta, bearing, northVec, eastVec, aSqr, ab, bSqr, mag, unitPos, result) { + var azimuth = theta + bearing; + var rotAxis = Cartesian3.multiplyByScalar(eastVec, Math.cos(azimuth)); + var tempVec = Cartesian3.multiplyByScalar(northVec, Math.sin(azimuth)); + Cartesian3.add(rotAxis, tempVec, rotAxis); + + var cosThetaSquared = Math.cos(theta); + cosThetaSquared = cosThetaSquared * cosThetaSquared; + + var sinThetaSquared = Math.sin(theta); + sinThetaSquared = sinThetaSquared * sinThetaSquared; + + var radius = ab / Math.sqrt(bSqr * cosThetaSquared + aSqr * sinThetaSquared); + var angle = radius / mag; + + // Create the quaternion to rotate the position vector to the boundary of the ellipse. + var unitQuat = Quaternion.fromAxisAngle(rotAxis, angle); + var rotMtx = Matrix3.fromQuaternion(unitQuat); + + Matrix3.multiplyByVector(rotMtx, unitPos, result); + Cartesian3.normalize(result, result); + Cartesian3.multiplyByScalar(result, mag, result); return result; } @@ -53,8 +68,6 @@ define([ var scratchCartesian2 = new Cartesian3(); var scratchCartesian3 = new Cartesian3(); var scratchCartesian4 = new Cartesian3(); - var scratchCartographic = new Cartographic(); - var scratchMatrix2 = new Matrix2(); /** * Computes vertices and indices for an ellipse on the ellipsoid. @@ -180,33 +193,14 @@ define([ var i; var j; - var numInterior; var theta; + var numInterior; + var t; + var interiorPosition; for (i = 0, theta = CesiumMath.PI_OVER_TWO; i < numPts && theta > 0; ++i, theta -= deltaTheta) { - var azimuth = theta + bearing; - var rotAxis = Cartesian3.multiplyByScalar(eastVec, Math.cos(azimuth)); - var tempVec = Cartesian3.multiplyByScalar(northVec, Math.sin(azimuth)); - Cartesian3.add(rotAxis, tempVec, rotAxis); - - var cosThetaSquared = Math.cos(theta); - cosThetaSquared = cosThetaSquared * cosThetaSquared; - - var sinThetaSquared = Math.sin(theta); - sinThetaSquared = sinThetaSquared * sinThetaSquared; - - var radius = ab / Math.sqrt(bSqr * cosThetaSquared + aSqr * sinThetaSquared); - var angle = radius / mag; - - // Create the quaternion to rotate the position vector to the boundary of the ellipse. - var unitQuat = Quaternion.fromAxisAngle(rotAxis, angle); - var rotMtx = Matrix3.fromQuaternion(unitQuat); - - Matrix3.multiplyByVector(rotMtx, unitPos, position); - Cartesian3.normalize(position, position); - Cartesian3.multiplyByScalar(position, mag, position); - - reflect(position, center, rotatedEastVec, reflectedPosition); + pointOnEllipsoid(theta, bearing, northVec, eastVec, aSqr, ab, bSqr, mag, unitPos, position); + pointOnEllipsoid(Math.PI - theta, bearing, northVec, eastVec, aSqr, ab, bSqr, mag, unitPos, reflectedPosition); positions[positionIndex++] = position.x; positions[positionIndex++] = position.y; @@ -214,8 +208,8 @@ define([ numInterior = 2 * i + 2; for (j = 1; j < numInterior - 1; ++j) { - var t = j / (numInterior - 1); - var interiorPosition = Cartesian3.lerp(position, reflectedPosition, t, scratchCartesian3); + t = j / (numInterior - 1); + interiorPosition = Cartesian3.lerp(position, reflectedPosition, t, scratchCartesian3); positions[positionIndex++] = interiorPosition.x; positions[positionIndex++] = interiorPosition.y; positions[positionIndex++] = interiorPosition.z; @@ -227,21 +221,29 @@ define([ } numPts = i; - var reverseIndex = positionIndex; - // Reflect the points across the north axis to get the other half of the ellipsoid. for (i = numPts; i > 0; --i) { - numInterior = 2 * i; - reverseIndex -= numInterior * 3; - for (j = 0; j < numInterior; ++j) { - var index = reverseIndex + j * 3; - Cartesian3.fromArray(positions, index, position); - reflect(position, center, rotatedNorthVec, reflectedPosition); - - positions[positionIndex++] = reflectedPosition.x; - positions[positionIndex++] = reflectedPosition.y; - positions[positionIndex++] = reflectedPosition.z; + theta = CesiumMath.PI_OVER_TWO - (i - 1) * deltaTheta; + + pointOnEllipsoid(-theta, bearing, northVec, eastVec, aSqr, ab, bSqr, mag, unitPos, position); + pointOnEllipsoid( theta + Math.PI, bearing, northVec, eastVec, aSqr, ab, bSqr, mag, unitPos, reflectedPosition); + + positions[positionIndex++] = position.x; + positions[positionIndex++] = position.y; + positions[positionIndex++] = position.z; + + numInterior = 2 * (i - 1) + 2; + for (j = 1; j < numInterior - 1; ++j) { + t = j / (numInterior - 1); + interiorPosition = Cartesian3.lerp(position, reflectedPosition, t, scratchCartesian3); + positions[positionIndex++] = interiorPosition.x; + positions[positionIndex++] = interiorPosition.y; + positions[positionIndex++] = interiorPosition.z; } + + positions[positionIndex++] = reflectedPosition.x; + positions[positionIndex++] = reflectedPosition.y; + positions[positionIndex++] = reflectedPosition.z; } // The original length may have been an over-estimate From 7a508214120a81f9cbf3cc29fd0601d7b3dc436d Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 30 May 2013 19:49:38 -0400 Subject: [PATCH 099/306] Some clean up, added code comments, and reduced number of allocations. --- Source/Core/EllipseGeometry.js | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/Source/Core/EllipseGeometry.js b/Source/Core/EllipseGeometry.js index 52b00b34ad34..e072515b7082 100644 --- a/Source/Core/EllipseGeometry.js +++ b/Source/Core/EllipseGeometry.js @@ -2,17 +2,13 @@ define([ './defaultValue', './BoundingSphere', - './Cartesian2', './Cartesian3', - './Cartographic', './ComponentDatatype', './DeveloperError', './Ellipsoid', - './GeographicProjection', './GeometryAttribute', './GeometryIndices', './Math', - './Matrix2', './Matrix3', './Matrix4', './PrimitiveType', @@ -21,17 +17,13 @@ define([ ], function( defaultValue, BoundingSphere, - Cartesian2, Cartesian3, - Cartographic, ComponentDatatype, DeveloperError, Ellipsoid, - GeographicProjection, GeometryAttribute, GeometryIndices, CesiumMath, - Matrix2, Matrix3, Matrix4, PrimitiveType, @@ -39,10 +31,16 @@ define([ VertexFormat) { "use strict"; + var rotAxis = new Cartesian3(); + var tempVec = new Cartesian3(); + var unitQuat = new Quaternion(); + var rotMtx = new Matrix3(); + function pointOnEllipsoid(theta, bearing, northVec, eastVec, aSqr, ab, bSqr, mag, unitPos, result) { var azimuth = theta + bearing; - var rotAxis = Cartesian3.multiplyByScalar(eastVec, Math.cos(azimuth)); - var tempVec = Cartesian3.multiplyByScalar(northVec, Math.sin(azimuth)); + + Cartesian3.multiplyByScalar(eastVec, Math.cos(azimuth), rotAxis); + Cartesian3.multiplyByScalar(northVec, Math.sin(azimuth), tempVec); Cartesian3.add(rotAxis, tempVec, rotAxis); var cosThetaSquared = Math.cos(theta); @@ -55,8 +53,8 @@ define([ var angle = radius / mag; // Create the quaternion to rotate the position vector to the boundary of the ellipse. - var unitQuat = Quaternion.fromAxisAngle(rotAxis, angle); - var rotMtx = Matrix3.fromQuaternion(unitQuat); + Quaternion.fromAxisAngle(rotAxis, angle, unitQuat); + Matrix3.fromQuaternion(unitQuat, rotMtx); Matrix3.multiplyByVector(rotMtx, unitPos, result); Cartesian3.normalize(result, result); @@ -178,16 +176,8 @@ define([ // for the whole ellipse. Note: this is just an estimate and may actually be less depending // on the number of iterations before the angle reaches pi/2. var size = 2 * numPts * (numPts + 1); - var positions = new Array(size * 3); var positionIndex = 0; - - var rotation = Matrix3.fromQuaternion(Quaternion.fromAxisAngle(unitPos, bearing)); - var rotatedNorthVec = Matrix3.multiplyByVector(rotation, northVec); - var rotatedEastVec = Matrix3.multiplyByVector(rotation, eastVec); - Cartesian3.normalize(rotatedNorthVec, rotatedNorthVec); - Cartesian3.normalize(rotatedEastVec, rotatedEastVec); - var position = scratchCartesian1; var reflectedPosition = scratchCartesian2; @@ -198,6 +188,7 @@ define([ var t; var interiorPosition; + // Compute points in the 'northern' half of the ellipse for (i = 0, theta = CesiumMath.PI_OVER_TWO; i < numPts && theta > 0; ++i, theta -= deltaTheta) { pointOnEllipsoid(theta, bearing, northVec, eastVec, aSqr, ab, bSqr, mag, unitPos, position); pointOnEllipsoid(Math.PI - theta, bearing, northVec, eastVec, aSqr, ab, bSqr, mag, unitPos, reflectedPosition); @@ -220,8 +211,10 @@ define([ positions[positionIndex++] = reflectedPosition.z; } + // Set numPts if theta reached zero numPts = i; + // Compute points in the 'northern' half of the ellipse for (i = numPts; i > 0; --i) { theta = CesiumMath.PI_OVER_TWO - (i - 1) * deltaTheta; From b302b2b08591cb5b8cf9ac2add03f45530485982 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 30 May 2013 19:52:56 -0400 Subject: [PATCH 100/306] Update the tests. --- Specs/Core/CircleGeometrySpec.js | 16 ++++++++-------- Specs/Core/EllipseGeometrySpec.js | 16 ++++++++-------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Specs/Core/CircleGeometrySpec.js b/Specs/Core/CircleGeometrySpec.js index 0043d4ac9b58..cf8a85a41922 100644 --- a/Specs/Core/CircleGeometrySpec.js +++ b/Specs/Core/CircleGeometrySpec.js @@ -59,8 +59,8 @@ defineSuite([ radius : 1.0 }); - expect(m.attributes.position.values.length).toEqual(3 * 32); - expect(m.indexLists[0].values.length).toEqual(3 * 48); + expect(m.attributes.position.values.length).toEqual(3 * 24); + expect(m.indexLists[0].values.length).toEqual(3 * 34); expect(m.boundingSphere.radius).toEqual(1); }); @@ -74,11 +74,11 @@ defineSuite([ radius : 1.0 }); - expect(m.attributes.position.values.length).toEqual(3 * 32); - expect(m.attributes.st.values.length).toEqual(2 * 32); - expect(m.attributes.normal.values.length).toEqual(3 * 32); - expect(m.attributes.tangent.values.length).toEqual(3 * 32); - expect(m.attributes.binormal.values.length).toEqual(3 * 32); - expect(m.indexLists[0].values.length).toEqual(3 * 48); + expect(m.attributes.position.values.length).toEqual(3 * 24); + expect(m.attributes.st.values.length).toEqual(2 * 24); + expect(m.attributes.normal.values.length).toEqual(3 * 24); + expect(m.attributes.tangent.values.length).toEqual(3 * 24); + expect(m.attributes.binormal.values.length).toEqual(3 * 24); + expect(m.indexLists[0].values.length).toEqual(3 * 34); }); }); diff --git a/Specs/Core/EllipseGeometrySpec.js b/Specs/Core/EllipseGeometrySpec.js index 7e0bcc1d2949..baf1f752281f 100644 --- a/Specs/Core/EllipseGeometrySpec.js +++ b/Specs/Core/EllipseGeometrySpec.js @@ -73,8 +73,8 @@ defineSuite([ semiMinorAxis : 1.0 }); - expect(m.attributes.position.values.length).toEqual(3 * 32); - expect(m.indexLists[0].values.length).toEqual(3 * 48); + expect(m.attributes.position.values.length).toEqual(3 * 24); + expect(m.indexLists[0].values.length).toEqual(3 * 34); expect(m.boundingSphere.radius).toEqual(1); }); @@ -89,11 +89,11 @@ defineSuite([ semiMinorAxis : 1.0 }); - expect(m.attributes.position.values.length).toEqual(3 * 32); - expect(m.attributes.st.values.length).toEqual(2 * 32); - expect(m.attributes.normal.values.length).toEqual(3 * 32); - expect(m.attributes.tangent.values.length).toEqual(3 * 32); - expect(m.attributes.binormal.values.length).toEqual(3 * 32); - expect(m.indexLists[0].values.length).toEqual(3 * 48); + expect(m.attributes.position.values.length).toEqual(3 * 24); + expect(m.attributes.st.values.length).toEqual(2 * 24); + expect(m.attributes.normal.values.length).toEqual(3 * 24); + expect(m.attributes.tangent.values.length).toEqual(3 * 24); + expect(m.attributes.binormal.values.length).toEqual(3 * 24); + expect(m.indexLists[0].values.length).toEqual(3 * 34); }); }); From ccfedab35ee5a75af3b308cb9057cd1330668fab Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 30 May 2013 20:08:47 -0400 Subject: [PATCH 101/306] Reverse triangle winding-order and re-enable backface culling. --- Source/Core/EllipseGeometry.js | 21 +++++++++++---------- Source/Scene/Appearance.js | 2 +- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/Source/Core/EllipseGeometry.js b/Source/Core/EllipseGeometry.js index e072515b7082..964f8a158e5c 100644 --- a/Source/Core/EllipseGeometry.js +++ b/Source/Core/EllipseGeometry.js @@ -365,23 +365,24 @@ define([ prevIndex = (i - 1) * i; indices[indicesIndex++] = positionIndex++; - indices[indicesIndex++] = positionIndex; indices[indicesIndex++] = prevIndex; + indices[indicesIndex++] = positionIndex; numInterior = 2 * i; for (j = 0; j < numInterior - 1; ++j) { - indices[indicesIndex++] = prevIndex++; + indices[indicesIndex++] = positionIndex; + indices[indicesIndex++] = prevIndex++; indices[indicesIndex++] = prevIndex; indices[indicesIndex++] = positionIndex++; - indices[indicesIndex++] = positionIndex; indices[indicesIndex++] = prevIndex; + indices[indicesIndex++] = positionIndex; } indices[indicesIndex++] = positionIndex++; - indices[indicesIndex++] = positionIndex; indices[indicesIndex++] = prevIndex; + indices[indicesIndex++] = positionIndex; } // Indices for central column of triangles @@ -389,13 +390,13 @@ define([ ++positionIndex; ++prevIndex; for (i = 0; i < numInterior - 1; ++i) { - indices[indicesIndex++] = prevIndex++; indices[indicesIndex++] = positionIndex; + indices[indicesIndex++] = prevIndex++; indices[indicesIndex++] = prevIndex; indices[indicesIndex++] = positionIndex++; - indices[indicesIndex++] = positionIndex; indices[indicesIndex++] = prevIndex; + indices[indicesIndex++] = positionIndex; } // Reverse the process creating indices to the 'right' of the north vector @@ -403,23 +404,23 @@ define([ ++positionIndex; for (i = numPts - 1; i > 0; --i) { indices[indicesIndex++] = prevIndex++; - indices[indicesIndex++] = positionIndex; indices[indicesIndex++] = prevIndex; + indices[indicesIndex++] = positionIndex; numInterior = 2 * i; for (j = 0; j < numInterior - 1; ++j) { - indices[indicesIndex++] = prevIndex++; indices[indicesIndex++] = positionIndex; + indices[indicesIndex++] = prevIndex++; indices[indicesIndex++] = prevIndex; indices[indicesIndex++] = positionIndex++; - indices[indicesIndex++] = positionIndex; indices[indicesIndex++] = prevIndex; + indices[indicesIndex++] = positionIndex; } indices[indicesIndex++] = prevIndex++; - indices[indicesIndex++] = positionIndex++; indices[indicesIndex++] = prevIndex++; + indices[indicesIndex++] = positionIndex++; } indices.length = indicesIndex; diff --git a/Source/Scene/Appearance.js b/Source/Scene/Appearance.js index 0247c56ec88a..ae6f1a5aab18 100644 --- a/Source/Scene/Appearance.js +++ b/Source/Scene/Appearance.js @@ -60,7 +60,7 @@ define([ Appearance.CLOSED_TRANSLUCENT = freezeObject(new Appearance({ renderState : { cull : { - //enabled : true, + enabled : true, face : CullFace.BACK }, depthTest : { From 3fe4f1ed56e0362138399bd09917522c55e543ea Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Fri, 31 May 2013 09:22:29 -0400 Subject: [PATCH 102/306] Added per-geometry color --- Apps/CesiumViewer/CesiumViewer.js | 64 ++++++++- Source/Core/BoxGeometry.js | 7 + Source/Core/EllipsoidGeometry.js | 7 + Source/Core/ExtentGeometry.js | 7 + Source/Core/Geometry.js | 7 + Source/Core/PolygonGeometry.js | 133 +++++++++--------- Source/Core/VertexFormat.js | 34 +++-- Source/Core/WallGeometry.js | 7 + Source/Scene/Appearance.js | 29 +++- Source/Scene/Primitive.js | 70 ++++++++- .../DefaultAppearanceFS.glsl | 2 +- .../DefaultAppearanceVS.glsl | 4 +- .../PerGeometryColorAppearanceFS.glsl | 15 ++ .../PerGeometryColorAppearanceVS.glsl | 22 +++ Specs/Core/GeometryFiltersSpec.js | 4 +- 15 files changed, 323 insertions(+), 89 deletions(-) rename Source/Shaders/{ => Appearances}/DefaultAppearanceFS.glsl (100%) rename Source/Shaders/{ => Appearances}/DefaultAppearanceVS.glsl (100%) create mode 100644 Source/Shaders/Appearances/PerGeometryColorAppearanceFS.glsl create mode 100644 Source/Shaders/Appearances/PerGeometryColorAppearanceVS.glsl diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index 756f594e2043..edf4d3136517 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -5,6 +5,7 @@ define([ 'dojo/io-query', 'dojo/parser', 'dojo/ready', + 'Core/Color', 'Core/Math', 'Core/Cartographic', 'Core/Cartesian3', @@ -13,6 +14,7 @@ define([ 'Core/Extent', 'Core/ExtentGeometry', 'Core/EllipsoidGeometry', + 'Core/PolygonGeometry', 'Core/BoxGeometry', 'Core/GeometryFilters', 'Core/VertexFormat', @@ -30,6 +32,7 @@ define([ ioQuery, parser, ready, + Color, CesiumMath, Cartographic, Cartesian3, @@ -38,6 +41,7 @@ define([ Extent, ExtentGeometry, EllipsoidGeometry, + PolygonGeometry, BoxGeometry, GeometryFilters, VertexFormat, @@ -71,34 +75,41 @@ define([ widget.fullscreen.viewModel.fullscreenElement(document.body); var scene = widget.scene; + var ellipsoid = widget.centralBody.getEllipsoid(); var mesh = new ExtentGeometry({ + vertexFormat : VertexFormat.POSITION_AND_NORMAL, extent : new Extent( CesiumMath.toRadians(-180.0), CesiumMath.toRadians(50.0), CesiumMath.toRadians(180.0), CesiumMath.toRadians(90.0)), - granularity : 0.006 // More than 64K vertices + granularity : 0.006, // More than 64K vertices + pickData : 'mesh', + color : Color.CORNFLOWERBLUE }); - mesh.pickData = 'mesh'; var mesh2 = new EllipsoidGeometry({ + vertexFormat : VertexFormat.POSITION_AND_NORMAL, ellipsoid : new Ellipsoid(500000.0, 500000.0, 1000000.0), modelMatrix : Matrix4.multiplyByTranslation(Transforms.eastNorthUpToFixedFrame( Ellipsoid.WGS84.cartographicToCartesian(Cartographic.fromDegrees(-95.59777, 40.03883))), new Cartesian3(0.0, 0.0, 500000.0)), - pickData : 'mesh2' + pickData : 'mesh2', + color : Color.AQUAMARINE.clone() }); + mesh2.color.alpha = 0.5; var mesh3 = new BoxGeometry({ - vertexFormat : VertexFormat.POSITION_ONLY, + vertexFormat : VertexFormat.POSITION_AND_NORMAL, dimensions : new Cartesian3(1000000.0, 1000000.0, 2000000.0), modelMatrix : Matrix4.multiplyByTranslation(Transforms.eastNorthUpToFixedFrame( Ellipsoid.WGS84.cartographicToCartesian(Cartographic.fromDegrees(-75.59777, 40.03883))), new Cartesian3(0.0, 0.0, 3000000.0)), - pickData : 'mesh3' + pickData : 'mesh3', + color : Color.BLANCHEDALMOND }); var primitive = new Primitive({ geometries : [mesh, mesh2, mesh3], - appearance : Appearance.CLOSED_TRANSLUCENT + appearance : Appearance.PER_GEOMETRY_COLOR_CLOSED_TRANSLUCENT }); widget.scene.getPrimitives().add(primitive); @@ -154,6 +165,47 @@ define([ }); widget.scene.getPrimitives().add(primitive2); + var polygonGeometry = new PolygonGeometry({ + polygonHierarchy : { + positions : ellipsoid.cartographicArrayToCartesianArray([ + Cartographic.fromDegrees(-109.0, 30.0), + Cartographic.fromDegrees(-95.0, 30.0), + Cartographic.fromDegrees(-95.0, 40.0), + Cartographic.fromDegrees(-109.0, 40.0) + ]), + holes : [{ + positions : ellipsoid.cartographicArrayToCartesianArray([ + Cartographic.fromDegrees(-107.0, 31.0), + Cartographic.fromDegrees(-107.0, 39.0), + Cartographic.fromDegrees(-97.0, 39.0), + Cartographic.fromDegrees(-97.0, 31.0) + ]), + holes : [{ + positions : ellipsoid.cartographicArrayToCartesianArray([ + Cartographic.fromDegrees(-105.0, 33.0), + Cartographic.fromDegrees(-99.0, 33.0), + Cartographic.fromDegrees(-99.0, 37.0), + Cartographic.fromDegrees(-105.0, 37.0) + ]), + holes : [{ + positions : ellipsoid.cartographicArrayToCartesianArray([ + Cartographic.fromDegrees(-103.0, 34.0), + Cartographic.fromDegrees(-101.0, 34.0), + Cartographic.fromDegrees(-101.0, 36.0), + Cartographic.fromDegrees(-103.0, 36.0) + ]) + }] + }] + }] + }, + pickData : 'polygon3' + }); + + widget.scene.getPrimitives().add(new Primitive({ + geometries : polygonGeometry, + appearance : Appearance.CLOSED_TRANSLUCENT + })); + var handler = new ScreenSpaceEventHandler(scene.getCanvas()); handler.setInputAction( function (movement) { diff --git a/Source/Core/BoxGeometry.js b/Source/Core/BoxGeometry.js index 3df6007c03c2..45fab1cf0d2e 100644 --- a/Source/Core/BoxGeometry.js +++ b/Source/Core/BoxGeometry.js @@ -397,6 +397,13 @@ define([ */ this.modelMatrix = defaultValue(options.modelMatrix, Matrix4.IDENTITY.clone()); + /** + * The color of the geometry when a per-geometry color appearance is used. + * + * @type Color + */ + this.color = options.color; + /** * DOC_TBA */ diff --git a/Source/Core/EllipsoidGeometry.js b/Source/Core/EllipsoidGeometry.js index fb8c1fcc84dd..7999e8cd00fb 100644 --- a/Source/Core/EllipsoidGeometry.js +++ b/Source/Core/EllipsoidGeometry.js @@ -346,6 +346,13 @@ define([ */ this.modelMatrix = defaultValue(options.modelMatrix, Matrix4.IDENTITY.clone()); + /** + * The color of the geometry when a per-geometry color appearance is used. + * + * @type Color + */ + this.color = options.color; + /** * DOC_TBA */ diff --git a/Source/Core/ExtentGeometry.js b/Source/Core/ExtentGeometry.js index 0e6391d97d5c..df8648bac1ba 100644 --- a/Source/Core/ExtentGeometry.js +++ b/Source/Core/ExtentGeometry.js @@ -334,6 +334,13 @@ define([ */ this.modelMatrix = defaultValue(options.modelMatrix, Matrix4.IDENTITY.clone()); + /** + * The color of the geometry when a per-geometry color appearance is used. + * + * @type Color + */ + this.color = options.color; + /** * DOC_TBA */ diff --git a/Source/Core/Geometry.js b/Source/Core/Geometry.js index 4dada281fa35..5ee7a66fce8c 100644 --- a/Source/Core/Geometry.js +++ b/Source/Core/Geometry.js @@ -38,6 +38,13 @@ define([ */ this.modelMatrix = defaultValue(options.modelMatrix, Matrix4.IDENTITY.clone()); + /** + * The color of the geometry when a per-geometry color appearance is used. + * + * @type Color + */ + this.color = options.color; + /** * DOC_TBA */ diff --git a/Source/Core/PolygonGeometry.js b/Source/Core/PolygonGeometry.js index 0cef36707d9e..55aed36f35b9 100644 --- a/Source/Core/PolygonGeometry.js +++ b/Source/Core/PolygonGeometry.js @@ -35,7 +35,31 @@ define([ Intersect) { "use strict"; - var ellipsoid; + function createMeshFromPositions(ellipsoid, positions, boundingSphere, outerPositions) { + var cleanedPositions = PolygonPipeline.cleanUp(positions); + if (cleanedPositions.length < 3) { + // Duplicate positions result in not enough positions to form a polygon. + return undefined; + } + + var tangentPlane = EllipsoidTangentPlane.fromPoints(cleanedPositions, ellipsoid); + var positions2D = tangentPlane.projectPointsOntoPlane(cleanedPositions); + + var originalWindingOrder = PolygonPipeline.computeWindingOrder2D(positions2D); + if (originalWindingOrder === WindingOrder.CLOCKWISE) { + positions2D.reverse(); + cleanedPositions.reverse(); + } + var indices = PolygonPipeline.earClip2D(positions2D); + // Checking bounding sphere with plane for quick reject + var minX = boundingSphere.center.x - boundingSphere.radius; + if ((minX < 0) && (BoundingSphere.intersect(boundingSphere, Cartesian4.UNIT_Y) === Intersect.INTERSECTING)) { + indices = PolygonPipeline.wrapLongitude(cleanedPositions, indices); + } + var mesh = PolygonPipeline.computeSubdivision(cleanedPositions, indices); + + return mesh; + } /** * Creates a PolygonGeometry. The polygon itself is either defined by an array of Cartesian points, @@ -57,51 +81,47 @@ define([ * @example * * // create a polygon from points - * var polygon = new Cesium.PolygonGeometry({ + * var geometry = new Cesium.PolygonGeometry({ * positions : ellipsoid.cartographicArrayToCartesianArray([ - * Cesium.Cartographic.fromDegrees(-72.0, 40.0), - * Cesium.Cartographic.fromDegrees(-70.0, 35.0), - * Cesium.Cartographic.fromDegrees(-75.0, 30.0), - * Cesium.Cartographic.fromDegrees(-70.0, 30.0), - * Cesium.Cartographic.fromDegrees(-68.0, 40.0) - * ]), + * Cesium.Cartographic.fromDegrees(-72.0, 40.0), + * Cesium.Cartographic.fromDegrees(-70.0, 35.0), + * Cesium.Cartographic.fromDegrees(-75.0, 30.0), + * Cesium.Cartographic.fromDegrees(-70.0, 30.0), + * Cesium.Cartographic.fromDegrees(-68.0, 40.0) + * ]), * pickData : 'polygon1' * }); * * // create a nested polygon with holes - * polygon = new Cesium.PolygonGeometry({ + * var geometryWithHole = new Cesium.PolygonGeometry({ * polygonHierarchy : { - * positions : ellipsoid.cartographicArrayToCartesianArray( - * [ - * Cesium.Cartographic.fromDegrees(-109.0, 30.0), - * Cesium.Cartographic.fromDegrees(-95.0, 30.0), - * Cesium.Cartographic.fromDegrees(-95.0, 40.0), - * Cesium.Cartographic.fromDegrees(-109.0, 40.0) - * ]), + * positions : ellipsoid.cartographicArrayToCartesianArray([ + * Cesium.Cartographic.fromDegrees(-109.0, 30.0), + * Cesium.Cartographic.fromDegrees(-95.0, 30.0), + * Cesium.Cartographic.fromDegrees(-95.0, 40.0), + * Cesium.Cartographic.fromDegrees(-109.0, 40.0) + * ]), * holes : [{ - * positions : ellipsoid.cartographicArrayToCartesianArray( - * [ - * Cesium.Cartographic.fromDegrees(-107.0, 31.0), - * Cesium.Cartographic.fromDegrees(-107.0, 39.0), - * Cesium.Cartographic.fromDegrees(-97.0, 39.0), - * Cesium.Cartographic.fromDegrees(-97.0, 31.0) - * ]), + * positions : ellipsoid.cartographicArrayToCartesianArray([ + * Cesium.Cartographic.fromDegrees(-107.0, 31.0), + * Cesium.Cartographic.fromDegrees(-107.0, 39.0), + * Cesium.Cartographic.fromDegrees(-97.0, 39.0), + * Cesium.Cartographic.fromDegrees(-97.0, 31.0) + * ]), * holes : [{ - * positions : ellipsoid.cartographicArrayToCartesianArray( - * [ - * Cesium.Cartographic.fromDegrees(-105.0, 33.0), - * Cesium.Cartographic.fromDegrees(-99.0, 33.0), - * Cesium.Cartographic.fromDegrees(-99.0, 37.0), - * Cesium.Cartographic.fromDegrees(-105.0, 37.0) - * ]), + * positions : ellipsoid.cartographicArrayToCartesianArray([ + * Cesium.Cartographic.fromDegrees(-105.0, 33.0), + * Cesium.Cartographic.fromDegrees(-99.0, 33.0), + * Cesium.Cartographic.fromDegrees(-99.0, 37.0), + * Cesium.Cartographic.fromDegrees(-105.0, 37.0) + * ]), * holes : [{ - * positions : ellipsoid.cartographicArrayToCartesianArray( - * [ - * Cesium.Cartographic.fromDegrees(-103.0, 34.0), - * Cesium.Cartographic.fromDegrees(-101.0, 34.0), - * Cesium.Cartographic.fromDegrees(-101.0, 36.0), - * Cesium.Cartographic.fromDegrees(-103.0, 36.0) - * ]) + * positions : ellipsoid.cartographicArrayToCartesianArray([ + * Cesium.Cartographic.fromDegrees(-103.0, 34.0), + * Cesium.Cartographic.fromDegrees(-101.0, 34.0), + * Cesium.Cartographic.fromDegrees(-101.0, 36.0), + * Cesium.Cartographic.fromDegrees(-103.0, 36.0) + * ]) * }] * }] * }] @@ -112,7 +132,7 @@ define([ var PolygonGeometry = function(options) { options = defaultValue(options, defaultValue.EMPTY_OBJECT); - ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84); + var ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84); var meshes = []; var mesh; @@ -126,7 +146,7 @@ define([ positions = options.positions; boundingSphere = BoundingSphere.fromPoints(positions); - mesh = createMeshFromPositions(positions, boundingSphere); + mesh = createMeshFromPositions(ellipsoid, positions, boundingSphere); if (typeof mesh !== 'undefined') { meshes.push(mesh); } @@ -181,7 +201,7 @@ define([ boundingSphere = BoundingSphere.fromPoints(outerPositions); for (i = 0; i < polygonHierarchy.length; i++) { - mesh = createMeshFromPositions(polygonHierarchy[i], boundingSphere); + mesh = createMeshFromPositions(ellipsoid, polygonHierarchy[i], boundingSphere); if (typeof mesh !== 'undefined') { meshes.push(mesh); } @@ -240,38 +260,19 @@ define([ */ this.modelMatrix = defaultValue(options.modelMatrix, Matrix4.IDENTITY.clone()); + /** + * The color of the geometry when a per-geometry color appearance is used. + * + * @type Color + */ + this.color = options.color; + /** * DOC_TBA */ this.pickData = options.pickData; }; - function createMeshFromPositions(positions, boundingSphere, outerPositions) { - var cleanedPositions = PolygonPipeline.cleanUp(positions); - if (cleanedPositions.length < 3) { - // Duplicate positions result in not enough positions to form a polygon. - return undefined; - } - - var tangentPlane = EllipsoidTangentPlane.fromPoints(cleanedPositions, ellipsoid); - var positions2D = tangentPlane.projectPointsOntoPlane(cleanedPositions); - - var originalWindingOrder = PolygonPipeline.computeWindingOrder2D(positions2D); - if (originalWindingOrder === WindingOrder.CLOCKWISE) { - positions2D.reverse(); - cleanedPositions.reverse(); - } - var indices = PolygonPipeline.earClip2D(positions2D); - // Checking bounding sphere with plane for quick reject - var minX = boundingSphere.center.x - boundingSphere.radius; - if ((minX < 0) && (BoundingSphere.intersect(boundingSphere, Cartesian4.UNIT_Y) === Intersect.INTERSECTING)) { - indices = PolygonPipeline.wrapLongitude(cleanedPositions, indices); - } - var mesh = PolygonPipeline.computeSubdivision(cleanedPositions, indices); - - return mesh; - } - return PolygonGeometry; }); diff --git a/Source/Core/VertexFormat.js b/Source/Core/VertexFormat.js index 0cc9bbd7bfca..a31aca3f8f4a 100644 --- a/Source/Core/VertexFormat.js +++ b/Source/Core/VertexFormat.js @@ -19,17 +19,17 @@ define([ /** * DOC_TBA */ - this.position = defaultValue(options.position, true); + this.position = defaultValue(options.position, false); /** * DOC_TBA */ - this.normal = defaultValue(options.normal, true); + this.normal = defaultValue(options.normal, false); /** * DOC_TBA */ - this.st = defaultValue(options.textureCoordinates, true); + this.st = defaultValue(options.st, false); /** * DOC_TBA @@ -41,28 +41,46 @@ define([ */ this.tangent = defaultValue(options.tangent, false); - // pickColor is also a reserved name added, when needed, for picking. + // Reserved names + // * color - for per-geometry color. + // * pickColor - for picking. }; /** * DOC_TBA */ - VertexFormat.DEFAULT = freezeObject(new VertexFormat()); + VertexFormat.DEFAULT = freezeObject(new VertexFormat({ + position : true, + normal : true, + st : true + })); /** * DOC_TBA */ VertexFormat.POSITION_ONLY = freezeObject(new VertexFormat({ - st : false, - textureCoordinates : false + position : true + })); + + /** + * DOC_TBA + * + * For use with per-geometry color appearance. + */ + VertexFormat.POSITION_AND_NORMAL = freezeObject(new VertexFormat({ + position : true, + normal : true })); /** * DOC_TBA */ VertexFormat.ALL = freezeObject(new VertexFormat({ + position : true, + normal : true, + st : true, binormal : true, - tangent : true + tangent : true })); return VertexFormat; diff --git a/Source/Core/WallGeometry.js b/Source/Core/WallGeometry.js index 74a6c7829a93..8eed7d593c9d 100644 --- a/Source/Core/WallGeometry.js +++ b/Source/Core/WallGeometry.js @@ -199,6 +199,13 @@ define([ */ this.modelMatrix = defaultValue(options.modelMatrix, Matrix4.IDENTITY.clone()); + /** + * The color of the geometry when a per-geometry color appearance is used. + * + * @type Color + */ + this.color = options.color; + /** * DOC_TBA */ diff --git a/Source/Scene/Appearance.js b/Source/Scene/Appearance.js index ae6f1a5aab18..a93eccee0856 100644 --- a/Source/Scene/Appearance.js +++ b/Source/Scene/Appearance.js @@ -5,8 +5,10 @@ define([ '../Renderer/CullFace', '../Renderer/BlendingState', './Material', - '../Shaders/DefaultAppearanceVS', - '../Shaders/DefaultAppearanceFS' + '../Shaders/Appearances/DefaultAppearanceVS', + '../Shaders/Appearances/DefaultAppearanceFS', + '../Shaders/Appearances/PerGeometryColorAppearanceVS', + '../Shaders/Appearances/PerGeometryColorAppearanceFS' ], function( defaultValue, freezeObject, @@ -14,7 +16,9 @@ define([ BlendingState, Material, DefaultAppearanceVS, - DefaultAppearanceFS) { + DefaultAppearanceFS, + PerGeometryColorAppearanceVS, + PerGeometryColorDefaultAppearanceFS) { "use strict"; /** @@ -71,5 +75,24 @@ define([ } })); + /** + * DOC_TBA + */ + Appearance.PER_GEOMETRY_COLOR_CLOSED_TRANSLUCENT = freezeObject(new Appearance({ + vertexShaderSource : PerGeometryColorAppearanceVS, + fragmentShaderSource : PerGeometryColorDefaultAppearanceFS, + renderState : { + cull : { + enabled : true, + face : CullFace.BACK + }, + depthTest : { + enabled : true + }, + depthMask : false, + blending : BlendingState.ALPHA_BLEND + } + })); + return Appearance; }); \ No newline at end of file diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index 435e38bd7881..2554e32405c5 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -78,6 +78,67 @@ define([ this._commandLists = new CommandLists(); }; + function hasPerGeometryColor(geometries) { + var perGeometryColor = false; + var length = geometries.length; + for (var i = 0; i < length; ++i) { + if (typeof geometries[i].color !== 'undefined') { + perGeometryColor = true; + break; + } + } + + return perGeometryColor; + } + + function addColorAttribute(primitive, geometries, context) { + var length = geometries.length; + + for (var i = 0; i < length; ++i) { + var geometry = geometries[i]; + var attributes = geometry.attributes; + var positionAttr = attributes.position; + var numberOfComponents = 4 * (positionAttr.values.length / positionAttr.componentsPerAttribute); + + attributes.color = new GeometryAttribute({ + componentDatatype : ComponentDatatype.UNSIGNED_BYTE, + componentsPerAttribute : 4, + normalize : true, + values : new Uint8Array(numberOfComponents) + }); + + var color = geometry.color; + + if (typeof color !== 'undefined') { + var red = Color.floatToByte(color.red); + var green = Color.floatToByte(color.green); + var blue = Color.floatToByte(color.blue); + var alpha = Color.floatToByte(color.alpha); + var values = attributes.color.values; + + for (var j = 0; j < numberOfComponents; j += 4) { + values[j] = red; + values[j + 1] = green; + values[j + 2] = blue; + values[j + 3] = alpha; + } + } + } + } + + function isPickable(geometries) { + var pickable = false; + var length = geometries.length; + for (var i = 0; i < length; ++i) { + if (typeof geometries[i].pickData !== 'undefined') { + pickable = true; + break; + } + } + + return pickable; + } + function addPickColorAttribute(primitive, geometries, context) { var length = geometries.length; @@ -222,8 +283,13 @@ define([ } function geometryPipeline(primitive, geometries, context) { + // Add color attribute if any geometries have per-geometry color + if (hasPerGeometryColor(geometries)) { + addColorAttribute(primitive, geometries, context); + } + // Add pickColor attribute if any geometries are pickable - if (Geometry.isPickable(geometries)) { + if (isPickable(geometries)) { addPickColorAttribute(primitive, geometries, context); } @@ -301,7 +367,7 @@ define([ var rs = context.createRenderState(appearance.renderState); var pickRS; - if (Geometry.isPickable(geometries)) { + if (isPickable(geometries)) { this._pickSP = context.getShaderCache().replaceShaderProgram(this._pickSP, vs, createPickFragmentShaderSource(fs, 'varying'), attributeIndices); pickRS = rs; } else { diff --git a/Source/Shaders/DefaultAppearanceFS.glsl b/Source/Shaders/Appearances/DefaultAppearanceFS.glsl similarity index 100% rename from Source/Shaders/DefaultAppearanceFS.glsl rename to Source/Shaders/Appearances/DefaultAppearanceFS.glsl index fa05750ce982..e46ecd59fa77 100644 --- a/Source/Shaders/DefaultAppearanceFS.glsl +++ b/Source/Shaders/Appearances/DefaultAppearanceFS.glsl @@ -1,7 +1,7 @@ +varying vec3 v_positionEC; varying vec3 v_normalEC; varying vec3 v_tangentEC; varying vec3 v_binormalEC; -varying vec3 v_positionEC; varying vec2 v_st; void main() diff --git a/Source/Shaders/DefaultAppearanceVS.glsl b/Source/Shaders/Appearances/DefaultAppearanceVS.glsl similarity index 100% rename from Source/Shaders/DefaultAppearanceVS.glsl rename to Source/Shaders/Appearances/DefaultAppearanceVS.glsl index 75b2321ba248..b53c37853f7a 100644 --- a/Source/Shaders/DefaultAppearanceVS.glsl +++ b/Source/Shaders/Appearances/DefaultAppearanceVS.glsl @@ -6,10 +6,10 @@ attribute vec3 binormal; attribute vec2 st; attribute vec4 pickColor; +varying vec3 v_positionEC; varying vec3 v_normalEC; varying vec3 v_tangentEC; varying vec3 v_binormalEC; -varying vec3 v_positionEC; varying vec2 v_st; varying vec4 czm_pickColor; @@ -17,10 +17,10 @@ void main() { vec4 p = czm_translateRelativeToEye(positionHigh, positionLow); + v_positionEC = (czm_modelViewRelativeToEye * p).xyz; // position in eye coordinates v_normalEC = czm_normal * normal; // normal in eye coordinates v_tangentEC = czm_normal * tangent; // tangent in eye coordinates v_binormalEC = czm_normal * binormal; // binormal in eye coordinates - v_positionEC = (czm_modelViewRelativeToEye * p).xyz; // position in eye coordinates v_st = st; czm_pickColor = pickColor; diff --git a/Source/Shaders/Appearances/PerGeometryColorAppearanceFS.glsl b/Source/Shaders/Appearances/PerGeometryColorAppearanceFS.glsl new file mode 100644 index 000000000000..5c61202be5cc --- /dev/null +++ b/Source/Shaders/Appearances/PerGeometryColorAppearanceFS.glsl @@ -0,0 +1,15 @@ +varying vec3 v_positionEC; +varying vec3 v_normalEC; +varying vec4 v_color; + +void main() +{ + //vec3 positionToEyeEC = -v_positionEC; + //czm_material material = czm_getDefaultMaterial(); + //materialInput.normalEC = normalize(v_normalEC); + //materialInput.positionToEyeEC = positionToEyeEC; + //materia.diffuse = v_color.rgb; + //material.alpha = v_color.a; + //gl_FragColor = czm_phong(normalize(positionToEyeEC), material); + gl_FragColor = v_color; +} diff --git a/Source/Shaders/Appearances/PerGeometryColorAppearanceVS.glsl b/Source/Shaders/Appearances/PerGeometryColorAppearanceVS.glsl new file mode 100644 index 000000000000..0226303cb52e --- /dev/null +++ b/Source/Shaders/Appearances/PerGeometryColorAppearanceVS.glsl @@ -0,0 +1,22 @@ +attribute vec3 positionHigh; +attribute vec3 positionLow; +attribute vec3 normal; +attribute vec4 color; +attribute vec4 pickColor; + +varying vec3 v_positionEC; +varying vec3 v_normalEC; +varying vec4 v_color; +varying vec4 czm_pickColor; + +void main() +{ + vec4 p = czm_translateRelativeToEye(positionHigh, positionLow); + + v_positionEC = (czm_modelViewRelativeToEye * p).xyz; // position in eye coordinates + v_normalEC = czm_normal * normal; // normal in eye coordinates + v_color = color; + czm_pickColor = pickColor; + + gl_Position = czm_modelViewProjectionRelativeToEye * p; +} diff --git a/Specs/Core/GeometryFiltersSpec.js b/Specs/Core/GeometryFiltersSpec.js index 4e8ee68db287..8c4137a53cee 100644 --- a/Specs/Core/GeometryFiltersSpec.js +++ b/Specs/Core/GeometryFiltersSpec.js @@ -1149,7 +1149,9 @@ defineSuite([ it ('GeometryFilters.computeTangentAndBinormal computes tangent and binormal for an EllipsoidGeometry', function() { var mesh = new EllipsoidGeometry(); - var expected = new EllipsoidGeometry({vertexFormat: new VertexFormat({tangent: true, binormal: true})}); + var expected = new EllipsoidGeometry({ + vertexFormat: VertexFormat.ALL + }); mesh = GeometryFilters.computeTangentAndBinormal(mesh); expect(mesh.attributes.tangent.values.slice(1000,1200)).toEqualEpsilon(expected.attributes.tangent.values.slice(1000,1200), CesiumMath.EPSILON1); From f20c8f5760e96349a68bb7c6e8b92bc4e4b3508c Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Fri, 31 May 2013 09:46:36 -0400 Subject: [PATCH 103/306] Cleaned up doc --- Source/Core/BoxGeometry.js | 1 + Source/Core/EllipsoidGeometry.js | 1 + Source/Core/ExtentGeometry.js | 27 +++++++++++++++------------ Source/Core/GeometryFilters.js | 3 +-- Source/Core/PolygonGeometry.js | 12 +++++++----- Source/Core/WallGeometry.js | 4 +++- 6 files changed, 28 insertions(+), 20 deletions(-) diff --git a/Source/Core/BoxGeometry.js b/Source/Core/BoxGeometry.js index 45fab1cf0d2e..84df64e53e16 100644 --- a/Source/Core/BoxGeometry.js +++ b/Source/Core/BoxGeometry.js @@ -34,6 +34,7 @@ define([ * @param {Cartesian3} [options.dimensions=new Cartesian3(1.0, 1.0, 1.0)] The width, depth, and height of the box stored in the x, y, and z coordinates of the Cartesian3, respectively. * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed. * @param {Matrix4} [options.modelMatrix] The model matrix for this box. + * @param {Color} [options.color] The color of the geometry when a per-geometry color appearance is used. * @param {DOC_TBA} [options.pickData] DOC_TBA * * @exception {DeveloperError} All dimensions components must be greater than or equal to zero. diff --git a/Source/Core/EllipsoidGeometry.js b/Source/Core/EllipsoidGeometry.js index 7999e8cd00fb..50c03174545c 100644 --- a/Source/Core/EllipsoidGeometry.js +++ b/Source/Core/EllipsoidGeometry.js @@ -124,6 +124,7 @@ define([ * @param {Number} [options.numberOfPartitions=32] The number of times to partition the ellipsoid in a plane formed by two radii in a single quadrant. * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed. * @param {Matrix4} [options.modelMatrix] The model matrix for this ellipsoid. + * @param {Color} [options.color] The color of the geometry when a per-geometry color appearance is used. * @param {DOC_TBA} [options.pickData] DOC_TBA * * @exception {DeveloperError} options.numberOfPartitions must be greater than zero. diff --git a/Source/Core/ExtentGeometry.js b/Source/Core/ExtentGeometry.js index df8648bac1ba..39fabb50008d 100644 --- a/Source/Core/ExtentGeometry.js +++ b/Source/Core/ExtentGeometry.js @@ -61,19 +61,22 @@ define([ /** * Creates geometry for a cartographic extent on an ellipsoid centered at the origin. * - * @param {Extent} description.extent A cartographic extent with north, south, east and west properties in radians. - * @param {Ellipsoid} [description.ellipsoid=Ellipsoid.WGS84] The ellipsoid on which the extent lies. - * @param {Number} [description.granularity=0.1] The distance, in radians, between each latitude and longitude. Determines the number of positions in the buffer. - * @param {Number} [description.surfaceHeight=0.0] The height from the surface of the ellipsoid. - * @param {Number} [description.rotation=0.0] The rotation of the extent in radians. A positive rotation is counter-clockwise. + * @param {Extent} options.extent A cartographic extent with north, south, east and west properties in radians. + * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid on which the extent lies. + * @param {Number} [options.granularity=0.1] The distance, in radians, between each latitude and longitude. Determines the number of positions in the buffer. + * @param {Number} [options.surfaceHeight=0.0] The height from the surface of the ellipsoid. + * @param {Number} [options.rotation=0.0] The rotation of the extent in radians. A positive rotation is counter-clockwise. + * @param {Matrix4} [options.modelMatrix] The model matrix for this geometry. + * @param {Color} [options.color] The color of the geometry when a per-geometry color appearance is used. + * @param {DOC_TBA} [options.pickData] DOC_TBA * - * @exception {DeveloperError} description.extent is required and must have north, south, east and west attributes. - * @exception {DeveloperError} description.extent.north must be in the interval [-Pi/2, Pi/2]. - * @exception {DeveloperError} description.extent.south must be in the interval [-Pi/2, Pi/2]. - * @exception {DeveloperError} description.extent.east must be in the interval [-Pi, Pi]. - * @exception {DeveloperError} description.extent.west must be in the interval [-Pi, Pi]. - * @exception {DeveloperError} description.extent.north must be greater than extent.south. - * @exception {DeveloperError} description.extent.east must be greater than extent.west. + * @exception {DeveloperError} options.extent is required and must have north, south, east and west attributes. + * @exception {DeveloperError} options.extent.north must be in the interval [-Pi/2, Pi/2]. + * @exception {DeveloperError} options.extent.south must be in the interval [-Pi/2, Pi/2]. + * @exception {DeveloperError} options.extent.east must be in the interval [-Pi, Pi]. + * @exception {DeveloperError} options.extent.west must be in the interval [-Pi, Pi]. + * @exception {DeveloperError} options.extent.north must be greater than extent.south. + * @exception {DeveloperError} options.extent.east must be greater than extent.west. * @exception {DeveloperError} Rotated extent is invalid. * * @see Extent diff --git a/Source/Core/GeometryFilters.js b/Source/Core/GeometryFilters.js index 539b095bf52b..42e6c2595342 100644 --- a/Source/Core/GeometryFilters.js +++ b/Source/Core/GeometryFilters.js @@ -994,7 +994,7 @@ define([ * Computes the tangent and binormal of all vertices in a geometry * This assumes a counter-clockwise vertex winding order. * - * Based on: Lengyel, Eric. “Computing Tangent Space Basis Vectors for an Arbitrary Mesh”. Terathon Software 3D Graphics Library, 2001. http://www.terathon.com/code/tangent.html + * Based on: Lengyel, Eric. Computing Tangent Space Basis Vectors for an Arbitrary Mesh. Terathon Software 3D Graphics Library, 2001. * * @param {Geometry} geometry The geometry for which to calculate tangents and binormals, which is modified in place. * @param {Object} geometry.attributes.position The vertices of the geometry @@ -1012,7 +1012,6 @@ define([ * * @example * geometry = GeometryFilters.computeTangentAndBinormal(geometry); - * */ var normalScratch = new Cartesian3(); var normalScale = new Cartesian3(); diff --git a/Source/Core/PolygonGeometry.js b/Source/Core/PolygonGeometry.js index 55aed36f35b9..0e2d955e18a5 100644 --- a/Source/Core/PolygonGeometry.js +++ b/Source/Core/PolygonGeometry.js @@ -68,11 +68,13 @@ define([ * @alias PolygonGeometry * @constructor * - * @param {Array} [positions] an array of positions that defined the corner points of the polygon - * @param {polygon hierarchy} [polygonHierarchy] a polygon hierarchy that can include holes - * @param {Number} [height=0.0] the height of the polygon, - * @param {Object} [pickData] the geometry pick data - * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] the ellipsoid to be used as a reference + * @param {Array} [options.positions] an array of positions that defined the corner points of the polygon + * @param {Object} [options.polygonHierarchy] a polygon hierarchy that can include holes + * @param {Number} [options.height=0.0] the height of the polygon, + * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] the ellipsoid to be used as a reference + * @param {Matrix4} [options.modelMatrix] The model matrix for this geometry. + * @param {Color} [options.color] The color of the geometry when a per-geometry color appearance is used. + * @param {DOC_TBA} [options.pickData] DOC_TBA * * @exception {DeveloperError} All dimensions components must be greater than or equal to zero. * @exception {DeveloperError} At least three positions required diff --git a/Source/Core/WallGeometry.js b/Source/Core/WallGeometry.js index 8eed7d593c9d..d6b55b19dc78 100644 --- a/Source/Core/WallGeometry.js +++ b/Source/Core/WallGeometry.js @@ -39,8 +39,10 @@ define([ * height, and the information in the positions array is disregarded * @param {Number} [bottom] optional, the bottom of the wall. if specified, the bottom of the wall is treated as * this height. otherwise its treated as 'ground' (the WGS84 ellipsoid height 0) - * @param {Object} [pickData] the geometry pick data * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] ellispoid for coordinate manipulation + * @param {Matrix4} [options.modelMatrix] The model matrix for this geometry. + * @param {Color} [options.color] The color of the geometry when a per-geometry color appearance is used. + * @param {DOC_TBA} [options.pickData] DOC_TBA * * @exception {DeveloperError} All dimensions components must be greater than or equal to zero. * @exception {DeveloperError} positions is required From 0b2637291c6776727a907f20fd5cfc29f40f1ff5 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Fri, 31 May 2013 13:19:29 -0400 Subject: [PATCH 104/306] Add color to ellipse and circle geometry. --- Apps/CesiumViewer/CesiumViewer.js | 5 +++-- Source/Core/CircleGeometry.js | 8 ++++++++ Source/Core/EllipseGeometry.js | 8 ++++++++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index 3670862c7ddd..d353ee26723c 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -111,14 +111,15 @@ define([ }); var mesh4 = new EllipseGeometry({ - vertexFormat : VertexFormat.POSITION_ONLY, + vertexFormat : VertexFormat.POSITION_AND_NORMAL, ellipsoid : ellipsoid, center : ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-100, 20)), semiMinorAxis : 500000.0, semiMajorAxis : 1000000.0, bearing : CesiumMath.PI_OVER_FOUR, height : 1000000.0, - pickData : 'mesh4' + pickData : 'mesh4', + color : Color.LIME }); var primitive = new Primitive({ diff --git a/Source/Core/CircleGeometry.js b/Source/Core/CircleGeometry.js index e4bc0be781d6..7abf74d72e30 100644 --- a/Source/Core/CircleGeometry.js +++ b/Source/Core/CircleGeometry.js @@ -24,6 +24,7 @@ define([ * @param {Number} [options.granularity=0.02] The angular distance between points on the circle in radians. * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed. * @param {Matrix4} [options.modelMatrix] The model matrix for this ellipsoid. + * @param {Color} [options.color] The color of the geometry when a per-geometry color appearance is used. * @param {DOC_TBA} [options.pickData] DOC_TBA * * @exception {DeveloperError} center is required. @@ -91,6 +92,13 @@ define([ */ this.modelMatrix = ellipseGeometry.modelMatrix; + /** + * The color of the geometry when a per-geometry color appearance is used. + * + * @type Color + */ + this.color = options.color; + /** * DOC_TBA */ diff --git a/Source/Core/EllipseGeometry.js b/Source/Core/EllipseGeometry.js index 964f8a158e5c..0f237a00f091 100644 --- a/Source/Core/EllipseGeometry.js +++ b/Source/Core/EllipseGeometry.js @@ -82,6 +82,7 @@ define([ * @param {Number} [options.granularity=0.02] The angular distance between points on the ellipse in radians. * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed. * @param {Matrix4} [options.modelMatrix] The model matrix for this ellipsoid. + * @param {Color} [options.color] The color of the geometry when a per-geometry color appearance is used. * @param {DOC_TBA} [options.pickData] DOC_TBA * * @exception {DeveloperError} center is required. @@ -464,6 +465,13 @@ define([ */ this.modelMatrix = defaultValue(options.modelMatrix, Matrix4.IDENTITY.clone()); + /** + * The color of the geometry when a per-geometry color appearance is used. + * + * @type Color + */ + this.color = options.color; + /** * DOC_TBA */ From 99aaa12220bc8221a2313c9d69e768e4b5377a3e Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Fri, 31 May 2013 14:41:23 -0400 Subject: [PATCH 105/306] Modify WallGeometry to follow the template of other geometry types. --- Source/Core/WallGeometry.js | 178 ++++++++++++++++++++---------------- 1 file changed, 98 insertions(+), 80 deletions(-) diff --git a/Source/Core/WallGeometry.js b/Source/Core/WallGeometry.js index d6b55b19dc78..f9f2d9153f6b 100644 --- a/Source/Core/WallGeometry.js +++ b/Source/Core/WallGeometry.js @@ -1,45 +1,54 @@ /*global define*/ define([ + './defaultValue', + './BoundingSphere', + './Cartesian3', + './Cartographic', + './ComponentDatatype', './DeveloperError', './Ellipsoid', + './GeometryAttribute', + './GeometryIndices', './Matrix4', - './ComponentDatatype', './PrimitiveType', - './defaultValue', - './BoundingSphere', - './GeometryAttribute', - './GeometryIndices' + './VertexFormat' ], function( + defaultValue, + BoundingSphere, + Cartesian3, + Cartographic, + ComponentDatatype, DeveloperError, Ellipsoid, + GeometryAttribute, + GeometryIndices, Matrix4, - ComponentDatatype, PrimitiveType, - defaultValue, - BoundingSphere, - GeometryAttribute, - GeometryIndices) { + VertexFormat) { "use strict"; + var scratchCartographic = new Cartographic(); + var scratchCartesian3Position = new Cartesian3(); + /** * Creates a wall, which is similar to a KML line string. A wall is defined by a series of points, - * which extrude down to the ground. Optionally they can extrude downwards to a specified height. + * which extrude down to the ground. Optionally, they can extrude downwards to a specified height. * The points in the wall can be offset by supplied terrain elevation data. * * @alias WallGeometry * @constructor * - * @param {Array} positions an array of Cartesian objects, which are the points of the wall - * @param {string} altitudeMode either 'absolute' or 'relativeToGround'. 'absolute' means the height - * is treated from the WGS84 ellipsoid. 'relativeToGround' means they are treated - * relative to the supplied terrain data - * @param {Array} [terrain] required if altitudeMode is 'relativeToGround'. has to denote the same points - * as in positions, with the ground elevation reflecting the terrain elevation - * @param {Number} [top] optional, the top of the wall. if specified, the top of the wall is treated as this - * height, and the information in the positions array is disregarded - * @param {Number} [bottom] optional, the bottom of the wall. if specified, the bottom of the wall is treated as - * this height. otherwise its treated as 'ground' (the WGS84 ellipsoid height 0) - * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] ellispoid for coordinate manipulation + * @param {Array} positions An array of Cartesian objects, which are the points of the wall. + * @param {String} altitudeMode 'absolute' means the height is treated from the WGS84 ellipsoid. + * 'relativeToGround' means they are treated relative to the supplied terrain data. + * @param {Array} [terrain] Required if altitudeMode is 'relativeToGround'. + * Has to denote the same points as in positions, with the ground elevation reflecting the terrain elevation. + * @param {Number} [top] The top of the wall. If specified, the top of the wall is treated as this + * height, and the information in the positions array is disregarded. + * @param {Number} [bottom] The bottom of the wall. If specified, the bottom of the wall is treated as + * this height. Otherwise, its treated as 'ground' (the WGS84 ellipsoid height 0). + * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid for coordinate manipulation + * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed. * @param {Matrix4} [options.modelMatrix] The model matrix for this geometry. * @param {Color} [options.color] The color of the geometry when a per-geometry color appearance is used. * @param {DOC_TBA} [options.pickData] DOC_TBA @@ -60,86 +69,87 @@ define([ * ]; * * // create a wall that spans from ground level to 10000 meters - * var wall1 = new Cesium.WallGeometry({ + * var wall = new Cesium.WallGeometry({ * altitudeMode : 'absolute', - * positions : ellipsoid.cartographicArrayToCartesianArray(positions), - * pickData : 'wall1' + * positions : ellipsoid.cartographicArrayToCartesianArray(positions) * }); * */ var WallGeometry = function(options) { options = defaultValue(options, defaultValue.EMPTY_OBJECT); - var positions; + var wallPositions = options.positions; + var altitudeMode = options.altitudeMode; + var terrain = options.terrain; + var top = options.top; + var bottom = options.bottom; + var ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84); + var vertexFormat = defaultValue(options.vertexFormat, VertexFormat.DEFAULT); - if (typeof options.positions !== 'undefined') { - positions = options.positions; - } else { + if (typeof wallPositions === 'undefined') { throw new DeveloperError('positions is required.'); } - var attributes = {}; - var indexLists = []; - - if (options.altitudeMode === 'relativeToGround' && typeof options.terrain === 'undefined') { + if (altitudeMode === 'relativeToGround' && typeof terrain === 'undefined') { throw new DeveloperError('No terrain supplied when required.'); } - if (typeof options.terrain !== 'undefined' && options.terrain.length !== positions.length) { + + if (typeof terrain !== 'undefined' && terrain.length !== wallPositions.length) { throw new DeveloperError('Coordinates and terrain points don\'t match in number'); } - var ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84); - - attributes.position = new GeometryAttribute({ - componentDatatype : ComponentDatatype.FLOAT, - componentsPerAttribute : 3, - values : new Array(positions.length * 6) - }); + var i; + var j; // add lower and upper points one after the other, lower // points being even and upper points being odd - var origHeight; - var c; - var values = attributes.position.values; - for (var i = 0, j = 0; i < positions.length; ++i) { - c = ellipsoid.cartesianToCartographic(positions[i]); - origHeight = c.height; + var positions = new Array(wallPositions.length * 6); + for (i = 0, j = 0; i < wallPositions.length; ++i) { + var c = ellipsoid.cartesianToCartographic(wallPositions[i], scratchCartographic); + var origHeight = c.height; c.height = 0.0; - if (options.bottom !== undefined) { - c.height = options.bottom; + + var terrainHeight = 0.0; + if (terrain !== undefined) { + var h = terrain[i].height; + if (!isNaN(h)) { + terrainHeight = h; + } } - if (options.terrain !== undefined && options.bottom !== undefined && - !isNaN(options.terrain[i].height)) { - c.height += options.terrain[i].height; + if (bottom !== undefined) { + c.height = bottom; + } else { + c.height += terrainHeight; } - var v = ellipsoid.cartographicToCartesian(c); + + var v = ellipsoid.cartographicToCartesian(c, scratchCartesian3Position); // insert the lower point - values[j++] = v.x; - values[j++] = v.y; - values[j++] = v.z; + positions[j++] = v.x; + positions[j++] = v.y; + positions[j++] = v.z; // get the original height back, or set the top value - c.height = options.top === undefined ? origHeight : options.top; - if (options.terrain !== undefined && !isNaN(options.terrain[i].height)) { - c.height += options.terrain[i].height; - } - v = ellipsoid.cartographicToCartesian(c); + c.height = (top === undefined) ? origHeight : top; + c.height += terrainHeight; + v = ellipsoid.cartographicToCartesian(c, scratchCartesian3Position); // insert the upper point - values[j++] = v.x; - values[j++] = v.y; - values[j++] = v.z; + positions[j++] = v.x; + positions[j++] = v.y; + positions[j++] = v.z; } - var noPoints1 = attributes.position.values.length / 3 - 2; + var attributes = {}; - indexLists.push( - new GeometryIndices({ - primitiveType : PrimitiveType.TRIANGLES, - values : new Array(noPoints1 * 3) - })); + if (vertexFormat.position) { + attributes.position = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : positions + }); + } // prepare the side walls, two triangles for each wall @@ -156,17 +166,20 @@ define([ // C (i) D (i+2) F // - var indexes = indexLists[0].values; - for (i = 0, j = 0; i < noPoints1; i += 2) { + var size = positions.length / 3 - 2; + var indices = new Array(size * 3); + + j = 0; + for (i = 0; i < size; i += 2) { // first do A C B - indexes[j++] = i + 1; - indexes[j++] = i; - indexes[j++] = i + 3; + indices[j++] = i + 1; + indices[j++] = i; + indices[j++] = i + 3; // now do B C D - indexes[j++] = i + 3; - indexes[j++] = i; - indexes[j++] = i + 2; + indices[j++] = i + 3; + indices[j++] = i; + indices[j++] = i + 2; } /** @@ -182,14 +195,19 @@ define([ * * @type Array */ - this.indexLists = indexLists; + this.indexLists = [ + new GeometryIndices({ + primitiveType : PrimitiveType.TRIANGLES, + values : indices + }) + ]; /** * A tight-fitting bounding sphere that encloses the vertices of the geometry. * * @type BoundingSphere */ - this.boundingSphere = new BoundingSphere.fromVertices(attributes.position.values); + this.boundingSphere = new BoundingSphere.fromVertices(positions); /** * The 4x4 transformation matrix that transforms the geometry from model to world coordinates. From 3925eb2cdea9f4b13011166ff65ffc5b79353855 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Fri, 31 May 2013 15:28:16 -0400 Subject: [PATCH 106/306] Add normal, tangent, binormal, and texture coordinate attributes to WallGeometry. --- Source/Core/WallGeometry.js | 124 +++++++++++++++++++++++++++++++----- 1 file changed, 107 insertions(+), 17 deletions(-) diff --git a/Source/Core/WallGeometry.js b/Source/Core/WallGeometry.js index f9f2d9153f6b..0a83aa5f55d3 100644 --- a/Source/Core/WallGeometry.js +++ b/Source/Core/WallGeometry.js @@ -28,7 +28,11 @@ define([ "use strict"; var scratchCartographic = new Cartographic(); - var scratchCartesian3Position = new Cartesian3(); + var scratchCartesian3Position1 = new Cartesian3(); + var scratchCartesian3Position2 = new Cartesian3(); + var scratchBinormal = new Cartesian3(); + var scratchTangent = new Cartesian3(); + var scratchNormal = new Cartesian3(); /** * Creates a wall, which is similar to a KML line string. A wall is defined by a series of points, @@ -99,12 +103,24 @@ define([ } var i; - var j; + var size = wallPositions.length * 2; + + var positions = (vertexFormat.position) ? new Array(size * 3) : undefined; + var normals = (vertexFormat.normal) ? new Array(size * 3) : undefined; + var tangents = (vertexFormat.tangent) ? new Array(size * 3) : undefined; + var binormals = (vertexFormat.binormal) ? new Array(size * 3) : undefined; + var textureCoordinates = (vertexFormat.st) ? new Array(size * 2) : undefined; + + var positionIndex = 0; + var normalIndex = 0; + var tangentIndex = 0; + var binormalIndex = 0; + var textureCoordIndex = 0; // add lower and upper points one after the other, lower // points being even and upper points being odd - var positions = new Array(wallPositions.length * 6); - for (i = 0, j = 0; i < wallPositions.length; ++i) { + var length = wallPositions.length; + for (i = 0; i < length; ++i) { var c = ellipsoid.cartesianToCartographic(wallPositions[i], scratchCartographic); var origHeight = c.height; c.height = 0.0; @@ -123,22 +139,64 @@ define([ c.height += terrainHeight; } - var v = ellipsoid.cartographicToCartesian(c, scratchCartesian3Position); - - // insert the lower point - positions[j++] = v.x; - positions[j++] = v.y; - positions[j++] = v.z; + var bottomPosition = ellipsoid.cartographicToCartesian(c, scratchCartesian3Position1); // get the original height back, or set the top value c.height = (top === undefined) ? origHeight : top; c.height += terrainHeight; - v = ellipsoid.cartographicToCartesian(c, scratchCartesian3Position); + var topPosition = ellipsoid.cartographicToCartesian(c, scratchCartesian3Position2); + + if (vertexFormat.position) { + // insert the lower point + positions[positionIndex++] = bottomPosition.x; + positions[positionIndex++] = bottomPosition.y; + positions[positionIndex++] = bottomPosition.z; + + // insert the upper point + positions[positionIndex++] = topPosition.x; + positions[positionIndex++] = topPosition.y; + positions[positionIndex++] = topPosition.z; + } + + if (vertexFormat.normal || vertexFormat.tangent || vertexFormat.binormal) { + var fromPrevious = (i === 0) ? Cartesian3.ZERO : Cartesian3.subtract(wallPositions[i], wallPositions[i - 1], scratchCartesian3Position1); + var toNext = (i === length - 1) ? Cartesian3.ZERO : Cartesian3.subtract(wallPositions[i + 1], wallPositions[i], scratchCartesian3Position2); + + var tangent = Cartesian3.add(fromPrevious, toNext, scratchTangent); + var binormal = Cartesian3.subtract(topPosition, bottomPosition, scratchBinormal); + + if (vertexFormat.normal) { + var normal = Cartesian3.cross(tangent, binormal, scratchNormal); + Cartesian3.normalize(normal, normal); + normals[normalIndex++] = normal.x; + normals[normalIndex++] = normal.y; + normals[normalIndex++] = normal.z; + } - // insert the upper point - positions[j++] = v.x; - positions[j++] = v.y; - positions[j++] = v.z; + if (vertexFormat.tangent) { + Cartesian3.normalize(tangent, tangent); + tangents[tangentIndex++] = tangent.x; + tangents[tangentIndex++] = tangent.y; + tangents[tangentIndex++] = tangent.z; + } + + if (vertexFormat.binormal) { + Cartesian3.normalize(binormal, binormal); + binormals[binormalIndex++] = binormal.x; + binormals[binormalIndex++] = binormal.y; + binormals[binormalIndex++] = binormal.z; + } + } + + if (vertexFormat.st) { + var s = i / (length - 1); + + textureCoordinates[textureCoordIndex++] = s; + textureCoordinates[textureCoordIndex++] = 0.0; + + textureCoordinates[textureCoordIndex++] = s; + textureCoordinates[textureCoordIndex++] = 1.0; + } } var attributes = {}; @@ -151,6 +209,38 @@ define([ }); } + if (vertexFormat.normal) { + attributes.normal = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : normals + }); + } + + if (vertexFormat.tangent) { + attributes.tangent = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : tangents + }); + } + + if (vertexFormat.binormal) { + attributes.binormal = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : binormals + }); + } + + if (vertexFormat.st) { + attributes.st = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 2, + values : textureCoordinates + }); + } + // prepare the side walls, two triangles for each wall // @@ -166,10 +256,10 @@ define([ // C (i) D (i+2) F // - var size = positions.length / 3 - 2; + size -= 2; var indices = new Array(size * 3); - j = 0; + var j = 0; for (i = 0; i < size; i += 2) { // first do A C B indices[j++] = i + 1; From bce212f43fad1e37a8ab791150c2d2c9ded0323b Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Fri, 31 May 2013 16:04:57 -0400 Subject: [PATCH 107/306] Update tests. --- Source/Core/WallGeometry.js | 19 +++-------- Specs/Core/WallGeometrySpec.js | 59 +++++++++++++++++++++------------- 2 files changed, 41 insertions(+), 37 deletions(-) diff --git a/Source/Core/WallGeometry.js b/Source/Core/WallGeometry.js index 0a83aa5f55d3..ef8f1d94a9f3 100644 --- a/Source/Core/WallGeometry.js +++ b/Source/Core/WallGeometry.js @@ -43,10 +43,7 @@ define([ * @constructor * * @param {Array} positions An array of Cartesian objects, which are the points of the wall. - * @param {String} altitudeMode 'absolute' means the height is treated from the WGS84 ellipsoid. - * 'relativeToGround' means they are treated relative to the supplied terrain data. - * @param {Array} [terrain] Required if altitudeMode is 'relativeToGround'. - * Has to denote the same points as in positions, with the ground elevation reflecting the terrain elevation. + * @param {Array} [terrain] Has to denote the same points as in positions, with the ground elevation reflecting the terrain elevation. * @param {Number} [top] The top of the wall. If specified, the top of the wall is treated as this * height, and the information in the positions array is disregarded. * @param {Number} [bottom] The bottom of the wall. If specified, the bottom of the wall is treated as @@ -57,10 +54,8 @@ define([ * @param {Color} [options.color] The color of the geometry when a per-geometry color appearance is used. * @param {DOC_TBA} [options.pickData] DOC_TBA * - * @exception {DeveloperError} All dimensions components must be greater than or equal to zero. - * @exception {DeveloperError} positions is required - * @exception {DeveloperError} No terrain supplied when required. - * @exception {DeveloperError} Coordinates and terrain points don't match in number + * @exception {DeveloperError} positions is required. + * @exception {DeveloperError} positions and terrain points must have the same length. * * @example * @@ -74,7 +69,6 @@ define([ * * // create a wall that spans from ground level to 10000 meters * var wall = new Cesium.WallGeometry({ - * altitudeMode : 'absolute', * positions : ellipsoid.cartographicArrayToCartesianArray(positions) * }); * @@ -83,7 +77,6 @@ define([ options = defaultValue(options, defaultValue.EMPTY_OBJECT); var wallPositions = options.positions; - var altitudeMode = options.altitudeMode; var terrain = options.terrain; var top = options.top; var bottom = options.bottom; @@ -94,12 +87,8 @@ define([ throw new DeveloperError('positions is required.'); } - if (altitudeMode === 'relativeToGround' && typeof terrain === 'undefined') { - throw new DeveloperError('No terrain supplied when required.'); - } - if (typeof terrain !== 'undefined' && terrain.length !== wallPositions.length) { - throw new DeveloperError('Coordinates and terrain points don\'t match in number'); + throw new DeveloperError('positions and terrain points must have the same length.'); } var i; diff --git a/Specs/Core/WallGeometrySpec.js b/Specs/Core/WallGeometrySpec.js index ee977831c093..637599f1d889 100644 --- a/Specs/Core/WallGeometrySpec.js +++ b/Specs/Core/WallGeometrySpec.js @@ -2,31 +2,42 @@ defineSuite([ 'Core/WallGeometry', 'Core/Cartographic', - 'Core/Ellipsoid' + 'Core/Ellipsoid', + 'Core/VertexFormat' ], function( WallGeometry, Cartographic, - Ellipsoid) { + Ellipsoid, + VertexFormat) { "use strict"; /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/ var ellipsoid = Ellipsoid.WGS84; - it('create with no parameters', function() { + it('throws with no positions', function() { expect(function() { return new WallGeometry({ }); }).toThrow(); }); - it('create simple absolute', function() { + it('throws when length of positions and terrain points are not equal', function() { + expect(function() { + return new WallGeometry({ + positions : new Array(3), + terrain : new Array(2) + }); + }).toThrow(); + }); + + it('creates positions relative to ellipsoid', function() { var coords = [ Cartographic.fromDegrees(49.0, 18.0, 1000.0), Cartographic.fromDegrees(50.0, 18.0, 1000.0) ]; var w = new WallGeometry({ - altitudeMode : 'absolute', + vertexFormat : VertexFormat.POSITION_ONLY, positions : ellipsoid.cartographicArrayToCartesianArray(coords) }); @@ -34,22 +45,7 @@ defineSuite([ expect(w.indexLists[0].values.length).toEqual(2 * 3); }); - it('create relative to ground no terrain', function() { - var coords = [ - Cartographic.fromDegrees(49.0, 18.0, 1000.0), - Cartographic.fromDegrees(50.0, 18.0, 1000.0) - ]; - - // this will throw an exception, as no terrain is specified - expect(function() { - return new WallGeometry({ - altitudeMode : 'relativeToGround', - positions : ellipsoid.cartographicArrayToCartesianArray(coords) - }).toThrow(); - }); - }); - - it('create relative to ground', function() { + it('creates positions relative to terrain', function() { var coords = [ Cartographic.fromDegrees(49.0, 18.0, 1000.0), Cartographic.fromDegrees(50.0, 18.0, 1000.0) @@ -61,7 +57,7 @@ defineSuite([ ]; var w = new WallGeometry({ - altitudeMode : 'relativeToGround', + vertexFormat : VertexFormat.POSITION_ONLY, positions : ellipsoid.cartographicArrayToCartesianArray(coords), terrain : terrain }); @@ -70,5 +66,24 @@ defineSuite([ expect(w.indexLists[0].values.length).toEqual(2 * 3); }); + it('creates all attributes', function() { + var coords = [ + Cartographic.fromDegrees(49.0, 18.0, 1000.0), + Cartographic.fromDegrees(50.0, 18.0, 1000.0), + Cartographic.fromDegrees(51.0, 18.0, 1000.0) + ]; + + var w = new WallGeometry({ + vertexFormat : VertexFormat.ALL, + positions : ellipsoid.cartographicArrayToCartesianArray(coords) + }); + + expect(w.attributes.position.values.length).toEqual(3 * 2 * 3); + expect(w.attributes.normal.values.length).toEqual(3 * 2 * 3); + expect(w.attributes.tangent.values.length).toEqual(3 * 2 * 3); + expect(w.attributes.binormal.values.length).toEqual(3 * 2 * 3); + expect(w.attributes.st.values.length).toEqual(3 * 2 * 2); + expect(w.indexLists[0].values.length).toEqual((3 * 2 - 2) * 3); + }); }); From 20a21979fb1a9df3cee6b59f4d052d2c32d20029 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Fri, 31 May 2013 19:34:02 -0400 Subject: [PATCH 108/306] Start adding more vertex attributes to polygon geometry. --- Source/Core/PolygonGeometry.js | 305 +++++++++++++++++++++------------ 1 file changed, 199 insertions(+), 106 deletions(-) diff --git a/Source/Core/PolygonGeometry.js b/Source/Core/PolygonGeometry.js index 0e2d955e18a5..1798b10e1dfd 100644 --- a/Source/Core/PolygonGeometry.js +++ b/Source/Core/PolygonGeometry.js @@ -1,41 +1,131 @@ /*global define*/ define([ - './DeveloperError', - './Cartesian4', - './Ellipsoid', - './Matrix4', - './ComponentDatatype', - './PrimitiveType', './defaultValue', + './BoundingRectangle', './BoundingSphere', - './GeometryAttribute', - './GeometryIndices', - './PolygonPipeline', + './Cartesian2', + './Cartesian3', + './Cartesian4', + './ComponentDatatype', + './DeveloperError', + './Ellipsoid', './EllipsoidTangentPlane', - './WindingOrder', + './GeometryAttribute', './GeometryFilters', + './Intersect', + './Matrix3', + './Matrix4', + './PolygonPipeline', + './Quaternion', './Queue', - './Intersect' + './VertexFormat', + './WindingOrder' ], function( - DeveloperError, - Cartesian4, - Ellipsoid, - Matrix4, - ComponentDatatype, - PrimitiveType, defaultValue, + BoundingRectangle, BoundingSphere, - GeometryAttribute, - GeometryIndices, - PolygonPipeline, + Cartesian2, + Cartesian3, + Cartesian4, + ComponentDatatype, + DeveloperError, + Ellipsoid, EllipsoidTangentPlane, - WindingOrder, + GeometryAttribute, GeometryFilters, + Intersect, + Matrix3, + Matrix4, + PolygonPipeline, + Quaternion, Queue, - Intersect) { + VertexFormat, + WindingOrder) { "use strict"; - function createMeshFromPositions(ellipsoid, positions, boundingSphere, outerPositions) { + var appendTextureCoordinatesOrigin = new Cartesian2(); + var appendTextureCoordinatesCartesian2 = new Cartesian2(); + var appendTextureCoordinatesCartesian3 = new Cartesian3(); + var appendTextureCoordinatesQuaternion = new Quaternion(); + var appendTextureCoordinatesMatrix3 = new Matrix3(); + + function appendTextureCoordinates(tangentPlane, boundingRectangle, mesh, angle) { + var origin = appendTextureCoordinatesOrigin; + origin.x = boundingRectangle.x; + origin.y = boundingRectangle.y; + + var positions = mesh.attributes.position.values; + var length = positions.length; + + var textureCoordinates = new Float32Array(2 * (length / 3)); + var j = 0; + + var rotation = Quaternion.fromAxisAngle(tangentPlane._plane.normal, angle, appendTextureCoordinatesQuaternion); + var textureMatrix = Matrix3.fromQuaternion(rotation, appendTextureCoordinatesMatrix3); + + for ( var i = 0; i < length; i += 3) { + var p = Cartesian3.fromArray(positions, i, appendTextureCoordinatesCartesian3); + Matrix3.multiplyByVector(textureMatrix, p, p); + var st = tangentPlane.projectPointOntoPlane(p, appendTextureCoordinatesCartesian2); + Cartesian3.subtract(st, origin, st); + + textureCoordinates[j++] = st.x / boundingRectangle.width; + textureCoordinates[j++] = st.y / boundingRectangle.height; + } + + mesh.attributes.st = { + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 2, + values : textureCoordinates + }; + + return mesh; + } + + var computeBoundingRectangleCartesian2 = new Cartesian2(); + var computeBoundingRectangleCartesian3 = new Cartesian3(); + var computeBoundingRectangleQuaternion = new Quaternion(); + var computeBoundingRectangleMatrix3 = new Matrix3(); + + function computeBoundingRectangle(tangentPlane, positions, angle, result) { + var rotation = Quaternion.fromAxisAngle(tangentPlane._plane.normal, angle, computeBoundingRectangleQuaternion); + var textureMatrix = Matrix3.fromQuaternion(rotation,computeBoundingRectangleMatrix3); + + var minX = Number.POSITIVE_INFINITY; + var maxX = Number.NEGATIVE_INFINITY; + var minY = Number.POSITIVE_INFINITY; + var maxY = Number.NEGATIVE_INFINITY; + + var length = positions.length; + for ( var i = 0; i < length; ++i) { + var p = Cartesian3.clone(positions[i], computeBoundingRectangleCartesian3); + Matrix3.multiplyByVector(textureMatrix, p, p); + var st = tangentPlane.projectPointOntoPlane(p, computeBoundingRectangleCartesian2); + + if (typeof st !== 'undefined') { + minX = Math.min(minX, st.x); + maxX = Math.max(maxX, st.x); + + minY = Math.min(minY, st.y); + maxY = Math.max(maxY, st.y); + } + } + + if (typeof result === 'undefined') { + result = new BoundingRectangle(); + } + + result.x = minX; + result.y = minY; + result.width = maxX - minX; + result.height = maxY - minY; + return result; + } + + var createMeshFromPositionsPositions = []; + var createMeshFromPositionsBoundingRectangle = new BoundingRectangle(); + + function createMeshFromPositions(ellipsoid, positions, boundingSphere, granularity, st, angle, outerPositions) { var cleanedPositions = PolygonPipeline.cleanUp(positions); if (cleanedPositions.length < 3) { // Duplicate positions result in not enough positions to form a polygon. @@ -43,119 +133,127 @@ define([ } var tangentPlane = EllipsoidTangentPlane.fromPoints(cleanedPositions, ellipsoid); - var positions2D = tangentPlane.projectPointsOntoPlane(cleanedPositions); + var positions2D = tangentPlane.projectPointsOntoPlane(cleanedPositions, createMeshFromPositionsPositions); var originalWindingOrder = PolygonPipeline.computeWindingOrder2D(positions2D); if (originalWindingOrder === WindingOrder.CLOCKWISE) { positions2D.reverse(); cleanedPositions.reverse(); } + var indices = PolygonPipeline.earClip2D(positions2D); + // Checking bounding sphere with plane for quick reject var minX = boundingSphere.center.x - boundingSphere.radius; if ((minX < 0) && (BoundingSphere.intersect(boundingSphere, Cartesian4.UNIT_Y) === Intersect.INTERSECTING)) { indices = PolygonPipeline.wrapLongitude(cleanedPositions, indices); } - var mesh = PolygonPipeline.computeSubdivision(cleanedPositions, indices); + + var mesh = PolygonPipeline.computeSubdivision(cleanedPositions, indices, granularity); + + if (st) { + var boundary = (typeof outerPositions === 'undefined') ? cleanedPositions : outerPositions; + var boundingRectangle = computeBoundingRectangle(tangentPlane, boundary, angle, createMeshFromPositionsBoundingRectangle); + mesh = appendTextureCoordinates(tangentPlane, boundingRectangle, mesh, angle); + } return mesh; } /** - * Creates a PolygonGeometry. The polygon itself is either defined by an array of Cartesian points, - * or a polygon hierarchy. + * Computes vertices and indices for a polygon on the ellipsoid. The polygon is either defined + * by an array of Cartesian points, or a polygon hierarchy. * * @alias PolygonGeometry * @constructor * - * @param {Array} [options.positions] an array of positions that defined the corner points of the polygon - * @param {Object} [options.polygonHierarchy] a polygon hierarchy that can include holes - * @param {Number} [options.height=0.0] the height of the polygon, - * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] the ellipsoid to be used as a reference + * @param {Array} [options.positions] An array of positions that defines the corner points of the polygon. + * @param {Object} [options.polygonHierarchy] A polygon hierarchy that can include holes. + * @param {Number} [options.height=0.0] The height of the polygon. + * @param {Number} [options.angle=0.0] The angle, in radians, to rotate the texture. Positive angles are counter-clockwise. + * @param {Number} [options.granularity=0.2] An arc distance used to determine how many points to generate when subdividing the polygon. + * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid to be used as a reference. + * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed. * @param {Matrix4} [options.modelMatrix] The model matrix for this geometry. * @param {Color} [options.color] The color of the geometry when a per-geometry color appearance is used. * @param {DOC_TBA} [options.pickData] DOC_TBA * - * @exception {DeveloperError} All dimensions components must be greater than or equal to zero. - * @exception {DeveloperError} At least three positions required - * @exception {DeveloperError} positions or polygonHierarchy must be supplied + * @exception {DeveloperError} At least three positions are required. + * @exception {DeveloperError} positions or polygonHierarchy must be supplied. * * @example + * // create a polygon from points + * var geometry = new Cesium.PolygonGeometry({ + * positions : ellipsoid.cartographicArrayToCartesianArray([ + * Cesium.Cartographic.fromDegrees(-72.0, 40.0), + * Cesium.Cartographic.fromDegrees(-70.0, 35.0), + * Cesium.Cartographic.fromDegrees(-75.0, 30.0), + * Cesium.Cartographic.fromDegrees(-70.0, 30.0), + * Cesium.Cartographic.fromDegrees(-68.0, 40.0) + * ]) + * }); * - * // create a polygon from points - * var geometry = new Cesium.PolygonGeometry({ - * positions : ellipsoid.cartographicArrayToCartesianArray([ - * Cesium.Cartographic.fromDegrees(-72.0, 40.0), - * Cesium.Cartographic.fromDegrees(-70.0, 35.0), - * Cesium.Cartographic.fromDegrees(-75.0, 30.0), - * Cesium.Cartographic.fromDegrees(-70.0, 30.0), - * Cesium.Cartographic.fromDegrees(-68.0, 40.0) - * ]), - * pickData : 'polygon1' - * }); - * - * // create a nested polygon with holes - * var geometryWithHole = new Cesium.PolygonGeometry({ - * polygonHierarchy : { - * positions : ellipsoid.cartographicArrayToCartesianArray([ - * Cesium.Cartographic.fromDegrees(-109.0, 30.0), - * Cesium.Cartographic.fromDegrees(-95.0, 30.0), - * Cesium.Cartographic.fromDegrees(-95.0, 40.0), - * Cesium.Cartographic.fromDegrees(-109.0, 40.0) - * ]), - * holes : [{ - * positions : ellipsoid.cartographicArrayToCartesianArray([ - * Cesium.Cartographic.fromDegrees(-107.0, 31.0), - * Cesium.Cartographic.fromDegrees(-107.0, 39.0), - * Cesium.Cartographic.fromDegrees(-97.0, 39.0), - * Cesium.Cartographic.fromDegrees(-97.0, 31.0) - * ]), - * holes : [{ - * positions : ellipsoid.cartographicArrayToCartesianArray([ - * Cesium.Cartographic.fromDegrees(-105.0, 33.0), - * Cesium.Cartographic.fromDegrees(-99.0, 33.0), - * Cesium.Cartographic.fromDegrees(-99.0, 37.0), - * Cesium.Cartographic.fromDegrees(-105.0, 37.0) - * ]), - * holes : [{ - * positions : ellipsoid.cartographicArrayToCartesianArray([ - * Cesium.Cartographic.fromDegrees(-103.0, 34.0), - * Cesium.Cartographic.fromDegrees(-101.0, 34.0), - * Cesium.Cartographic.fromDegrees(-101.0, 36.0), - * Cesium.Cartographic.fromDegrees(-103.0, 36.0) - * ]) - * }] + * // create a nested polygon with holes + * var geometryWithHole = new Cesium.PolygonGeometry({ + * polygonHierarchy : { + * positions : ellipsoid.cartographicArrayToCartesianArray([ + * Cesium.Cartographic.fromDegrees(-109.0, 30.0), + * Cesium.Cartographic.fromDegrees(-95.0, 30.0), + * Cesium.Cartographic.fromDegrees(-95.0, 40.0), + * Cesium.Cartographic.fromDegrees(-109.0, 40.0) + * ]), + * holes : [{ + * positions : ellipsoid.cartographicArrayToCartesianArray([ + * Cesium.Cartographic.fromDegrees(-107.0, 31.0), + * Cesium.Cartographic.fromDegrees(-107.0, 39.0), + * Cesium.Cartographic.fromDegrees(-97.0, 39.0), + * Cesium.Cartographic.fromDegrees(-97.0, 31.0) + * ]), + * holes : [{ + * positions : ellipsoid.cartographicArrayToCartesianArray([ + * Cesium.Cartographic.fromDegrees(-105.0, 33.0), + * Cesium.Cartographic.fromDegrees(-99.0, 33.0), + * Cesium.Cartographic.fromDegrees(-99.0, 37.0), + * Cesium.Cartographic.fromDegrees(-105.0, 37.0) + * ]), + * holes : [{ + * positions : ellipsoid.cartographicArrayToCartesianArray([ + * Cesium.Cartographic.fromDegrees(-103.0, 34.0), + * Cesium.Cartographic.fromDegrees(-101.0, 34.0), + * Cesium.Cartographic.fromDegrees(-101.0, 36.0), + * Cesium.Cartographic.fromDegrees(-103.0, 36.0) + * ]) + * }] * }] - * }] - * }, - * pickData : 'polygon3' - * }); + * }] + * } + * }); */ var PolygonGeometry = function(options) { options = defaultValue(options, defaultValue.EMPTY_OBJECT); + var positions = options.positions; + var polygonHierarchy = options.polygonHierarchy; + var height = defaultValue(options.height, 0.0); + var angle = defaultValue(options.angle, 0.0); + var granularity = defaultValue(options.granularity, 0.02); var ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84); + var vertexFormat = defaultValue(options.vertexFormat, VertexFormat.DEFAULT); var meshes = []; var mesh; var boundingSphere; var i; - var positions; - var polygonHierarchy; - if (typeof options.positions !== 'undefined') { + if (typeof positions !== 'undefined') { // create from positions - positions = options.positions; - boundingSphere = BoundingSphere.fromPoints(positions); - mesh = createMeshFromPositions(ellipsoid, positions, boundingSphere); + mesh = createMeshFromPositions(ellipsoid, positions, boundingSphere, granularity, vertexFormat.st, angle); if (typeof mesh !== 'undefined') { meshes.push(mesh); } - } else if (typeof options.polygonHierarchy !== 'undefined') { + } else if (typeof polygonHierarchy !== 'undefined') { // create from a polygon hierarchy - polygonHierarchy = options.polygonHierarchy; - // Algorithm adapted from http://www.geometrictools.com/Documentation/TriangulationByEarClipping.pdf var polygons = []; var queue = new Queue(); @@ -203,7 +301,7 @@ define([ boundingSphere = BoundingSphere.fromPoints(outerPositions); for (i = 0; i < polygonHierarchy.length; i++) { - mesh = createMeshFromPositions(ellipsoid, polygonHierarchy[i], boundingSphere); + mesh = createMeshFromPositions(ellipsoid, polygonHierarchy[i], boundingSphere, granularity, vertexFormat.st, angle, outerPositions); if (typeof mesh !== 'undefined') { meshes.push(mesh); } @@ -212,23 +310,18 @@ define([ throw new DeveloperError('positions or hierarchy must be supplied.'); } - var attributes = {}; - var indexLists = []; - mesh = GeometryFilters.combine(meshes); - mesh = PolygonPipeline.scaleToGeodeticHeight(mesh, defaultValue(options.height, 0.0), ellipsoid); + mesh = PolygonPipeline.scaleToGeodeticHeight(mesh, height, ellipsoid); - attributes.position = new GeometryAttribute({ - componentDatatype : ComponentDatatype.FLOAT, - componentsPerAttribute : 3, - values : mesh.attributes.position.values - }); + var attributes = {}; + + if (vertexFormat.position) { + attributes.position = mesh.attributes.position; + } - indexLists.push( - new GeometryIndices({ - primitiveType : PrimitiveType.TRIANGLES, - values : mesh.indexLists[0].values - })); + if (vertexFormat.st) { + attributes.st = mesh.attributes.st; + } /** * An object containing {@link GeometryAttribute} properties named after each of the @@ -243,7 +336,7 @@ define([ * * @type Array */ - this.indexLists = indexLists; + this.indexLists = mesh.indexLists; /** * A tight-fitting bounding sphere that encloses the vertices of the geometry. From e54313166c9a51cfa4a28f4c1836d518ac4fdae6 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Wed, 29 May 2013 16:42:43 -0400 Subject: [PATCH 109/306] Start approximate LVLH. --- Source/DynamicScene/DynamicObjectView.js | 48 +++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/Source/DynamicScene/DynamicObjectView.js b/Source/DynamicScene/DynamicObjectView.js index f8e8c17f89f3..7dbe54b4b438 100644 --- a/Source/DynamicScene/DynamicObjectView.js +++ b/Source/DynamicScene/DynamicObjectView.js @@ -9,6 +9,7 @@ define([ '../Core/Cartographic', '../Core/Quaternion', '../Core/Matrix3', + '../Core/Matrix4', '../Core/Ellipsoid', '../Core/Transforms', '../Scene/CameraColumbusViewMode', @@ -23,6 +24,7 @@ define([ Cartographic, Quaternion, Matrix3, + Matrix4, Ellipsoid, Transforms, CameraColumbusViewMode, @@ -81,7 +83,51 @@ define([ var cartesian = positionProperty.getValueCartesian(time, that._lastCartesian); if (typeof cartesian !== 'undefined') { - camera.transform = Transforms.eastNorthUpToFixedFrame(cartesian, ellipsoid, update3DTransform); + //if (that.referenceFrameType === ReferenceFrameType.EAST_NORTH_UP) { + // camera.transform = Transforms.eastNorthUpToFixedFrame(cartesian, ellipsoid, update3DTransform); + //} else if (that.referenceFrameType === ReferenceFrameType.LOCAL_VERTICAL_LOCAL_HORIZONTAL) { + var deltaTime = time.addSeconds(0.001); + var deltaCartesian = positionProperty.getValueCartesian(deltaTime); + if (typeof deltaCartesian !== 'undefined') { + var toInertial = Transforms.computeFixedToIcrfMatrix(time); + var toFixed = Transforms.computeIcrfToFixedMatrix(time); + + + // Z along the position + var zBasis = new Cartesian3(); + Cartesian3.normalize(cartesian, zBasis); + Cartesian3.normalize(deltaCartesian, deltaCartesian); + + Matrix3.multiplyByVector(toInertial, zBasis, zBasis); + Matrix3.multiplyByVector(toInertial, deltaCartesian, deltaCartesian); + + // Y is along the angular momentum vector (e.g. "orbit normal") + var yBasis = Cartesian3.cross(zBasis, deltaCartesian); + + //Cartesian3.normalize(zBasis, zBasis); + Cartesian3.normalize(yBasis, yBasis); + + // X is along the cross of y and z (right handed basis / in the direction of motion) + var xBasis = Cartesian3.cross(yBasis, zBasis); + + Cartesian3.normalize(xBasis, xBasis); + + Matrix3.multiplyByVector(toFixed, xBasis, xBasis); + Matrix3.multiplyByVector(toFixed, yBasis, yBasis); + Matrix3.multiplyByVector(toFixed, zBasis, zBasis); + + Cartesian3.normalize(xBasis, xBasis); + Cartesian3.normalize(yBasis, yBasis); + Cartesian3.normalize(zBasis, zBasis); + + camera.transform = new Matrix4( + xBasis.x, yBasis.x, zBasis.x, cartesian.x, + xBasis.y, yBasis.y, zBasis.y, cartesian.y, + xBasis.z, yBasis.z, zBasis.z, cartesian.z, + 0.0, 0.0, 0.0, 1.0); + } + //} + that._screenSpaceCameraController.setEllipsoid(Ellipsoid.UNIT_SPHERE); var position = camera.position; From 07c13a2109ead150e91b4149a37bc13b1701a118 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Wed, 29 May 2013 18:06:05 -0400 Subject: [PATCH 110/306] Fix LVLH transform. Thanks @rcpage3! --- Source/DynamicScene/DynamicObjectView.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Source/DynamicScene/DynamicObjectView.js b/Source/DynamicScene/DynamicObjectView.js index 7dbe54b4b438..c2b86e60b180 100644 --- a/Source/DynamicScene/DynamicObjectView.js +++ b/Source/DynamicScene/DynamicObjectView.js @@ -86,10 +86,11 @@ define([ //if (that.referenceFrameType === ReferenceFrameType.EAST_NORTH_UP) { // camera.transform = Transforms.eastNorthUpToFixedFrame(cartesian, ellipsoid, update3DTransform); //} else if (that.referenceFrameType === ReferenceFrameType.LOCAL_VERTICAL_LOCAL_HORIZONTAL) { - var deltaTime = time.addSeconds(0.001); + var deltaTime = time.addSeconds(1.0); var deltaCartesian = positionProperty.getValueCartesian(deltaTime); if (typeof deltaCartesian !== 'undefined') { var toInertial = Transforms.computeFixedToIcrfMatrix(time); + var toInertialDelta = Transforms.computeFixedToIcrfMatrix(deltaTime); var toFixed = Transforms.computeIcrfToFixedMatrix(time); @@ -99,7 +100,7 @@ define([ Cartesian3.normalize(deltaCartesian, deltaCartesian); Matrix3.multiplyByVector(toInertial, zBasis, zBasis); - Matrix3.multiplyByVector(toInertial, deltaCartesian, deltaCartesian); + Matrix3.multiplyByVector(toInertialDelta, deltaCartesian, deltaCartesian); // Y is along the angular momentum vector (e.g. "orbit normal") var yBasis = Cartesian3.cross(zBasis, deltaCartesian); From 7cbd1a3351cb37a5534d8b187f83892fc21b85ea Mon Sep 17 00:00:00 2001 From: andre-nunes Date: Thu, 30 May 2013 02:02:31 +0100 Subject: [PATCH 111/306] Replace pseudo-private functions with file-scoped functions --- .../CompositeDynamicObjectCollection.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Source/DynamicScene/CompositeDynamicObjectCollection.js b/Source/DynamicScene/CompositeDynamicObjectCollection.js index d551b56dac32..f666a852e48a 100644 --- a/Source/DynamicScene/CompositeDynamicObjectCollection.js +++ b/Source/DynamicScene/CompositeDynamicObjectCollection.js @@ -149,7 +149,7 @@ define([ var objects = collection.getObjects(); for ( var iObjects = objects.length - 1; iObjects > -1; iObjects--) { var object = objects[iObjects]; - var compositeObject = this._getOrCreateObject(object.id); + var compositeObject = getOrCreateObject(this, object.id); for ( var iMergeFuncs = thisMergeFunctions.length - 1; iMergeFuncs > -1; iMergeFuncs--) { var mergeFunc = thisMergeFunctions[iMergeFuncs]; mergeFunc(compositeObject, object); @@ -193,15 +193,15 @@ define([ this.setCollections([]); }; - CompositeDynamicObjectCollection.prototype._getOrCreateObject = function(id) { - var obj = this._hash[id]; + function getOrCreateObject(compositeDynamicObjectCollection, id) { + var obj = compositeDynamicObjectCollection._hash[id]; if (!obj) { obj = new DynamicObject(id); - this._hash[id] = obj; - this._array.push(obj); + compositeDynamicObjectCollection._hash[id] = obj; + compositeDynamicObjectCollection._array.push(obj); } return obj; - }; + } CompositeDynamicObjectCollection.prototype._clearObjects = function() { var removedObjects = this._array; @@ -227,7 +227,7 @@ define([ deleteFunc(compositeObject); } } else { - compositeObject = this._getOrCreateObject(updatedObject.id); + compositeObject = getOrCreateObject(this, updatedObject.id); } compositeObjects.push(compositeObject); From 4b26560576b802a12317e8e0f4f96b4b5431c56c Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 30 May 2013 20:48:42 -0400 Subject: [PATCH 112/306] Default to east-north-up frame if LVLH fails. --- Source/DynamicScene/DynamicObjectView.js | 46 +++++++++++++----------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/Source/DynamicScene/DynamicObjectView.js b/Source/DynamicScene/DynamicObjectView.js index c2b86e60b180..e91f95930166 100644 --- a/Source/DynamicScene/DynamicObjectView.js +++ b/Source/DynamicScene/DynamicObjectView.js @@ -83,34 +83,32 @@ define([ var cartesian = positionProperty.getValueCartesian(time, that._lastCartesian); if (typeof cartesian !== 'undefined') { - //if (that.referenceFrameType === ReferenceFrameType.EAST_NORTH_UP) { - // camera.transform = Transforms.eastNorthUpToFixedFrame(cartesian, ellipsoid, update3DTransform); - //} else if (that.referenceFrameType === ReferenceFrameType.LOCAL_VERTICAL_LOCAL_HORIZONTAL) { - var deltaTime = time.addSeconds(1.0); - var deltaCartesian = positionProperty.getValueCartesian(deltaTime); - if (typeof deltaCartesian !== 'undefined') { - var toInertial = Transforms.computeFixedToIcrfMatrix(time); - var toInertialDelta = Transforms.computeFixedToIcrfMatrix(deltaTime); - var toFixed = Transforms.computeIcrfToFixedMatrix(time); + var failed = false; + var deltaTime = time.addSeconds(1.0); + var deltaCartesian = positionProperty.getValueCartesian(deltaTime); + if (typeof deltaCartesian !== 'undefined' && !Cartesian3.equalsEpsilon(cartesian, deltaCartesian, CesiumMath.EPSILON6)) { + var toInertial = Transforms.computeFixedToIcrfMatrix(time); + var toInertialDelta = Transforms.computeFixedToIcrfMatrix(deltaTime); + var toFixed = Transforms.computeIcrfToFixedMatrix(time); - // Z along the position - var zBasis = new Cartesian3(); - Cartesian3.normalize(cartesian, zBasis); - Cartesian3.normalize(deltaCartesian, deltaCartesian); - Matrix3.multiplyByVector(toInertial, zBasis, zBasis); - Matrix3.multiplyByVector(toInertialDelta, deltaCartesian, deltaCartesian); + // Z along the position + var zBasis = new Cartesian3(); + Cartesian3.normalize(cartesian, zBasis); + Cartesian3.normalize(deltaCartesian, deltaCartesian); - // Y is along the angular momentum vector (e.g. "orbit normal") - var yBasis = Cartesian3.cross(zBasis, deltaCartesian); + Matrix3.multiplyByVector(toInertial, zBasis, zBasis); + Matrix3.multiplyByVector(toInertialDelta, deltaCartesian, deltaCartesian); - //Cartesian3.normalize(zBasis, zBasis); + // Y is along the angular momentum vector (e.g. "orbit normal") + var yBasis = Cartesian3.cross(zBasis, deltaCartesian); + if (!Cartesian3.equalsEpsilon(yBasis, Cartesian3.ZERO, CesiumMath.EPSILON6)) { + Cartesian3.normalize(zBasis, zBasis); Cartesian3.normalize(yBasis, yBasis); // X is along the cross of y and z (right handed basis / in the direction of motion) var xBasis = Cartesian3.cross(yBasis, zBasis); - Cartesian3.normalize(xBasis, xBasis); Matrix3.multiplyByVector(toFixed, xBasis, xBasis); @@ -126,8 +124,16 @@ define([ xBasis.y, yBasis.y, zBasis.y, cartesian.y, xBasis.z, yBasis.z, zBasis.z, cartesian.z, 0.0, 0.0, 0.0, 1.0); + } else { + failed = true; } - //} + } else { + failed = true; + } + + if (failed) { + camera.transform = Transforms.eastNorthUpToFixedFrame(cartesian, ellipsoid, update3DTransform); + } that._screenSpaceCameraController.setEllipsoid(Ellipsoid.UNIT_SPHERE); From c044c4f3cb40a3293cac720715953009a673140f Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 30 May 2013 20:54:55 -0400 Subject: [PATCH 113/306] Clean up some allocations. --- Source/DynamicScene/DynamicObjectView.js | 25 +++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/Source/DynamicScene/DynamicObjectView.js b/Source/DynamicScene/DynamicObjectView.js index e91f95930166..ff8d969e2eb8 100644 --- a/Source/DynamicScene/DynamicObjectView.js +++ b/Source/DynamicScene/DynamicObjectView.js @@ -78,6 +78,13 @@ define([ } var update3DTransform; + var update3DMatrix3Scratch1 = new Matrix3(); + var update3DMatrix3Scratch2 = new Matrix3(); + var update3DMatrix3Scratch3 = new Matrix3(); + var update3DCartesian3Scratch1 = new Cartesian3(); + var update3DCartesian3Scratch2 = new Cartesian3(); + var update3DCartesian3Scratch3 = new Cartesian3(); + function update3D(that, camera, objectChanged, offset, positionProperty, time, ellipsoid) { update3DController(that, camera, objectChanged, offset); @@ -86,15 +93,15 @@ define([ var failed = false; var deltaTime = time.addSeconds(1.0); - var deltaCartesian = positionProperty.getValueCartesian(deltaTime); + var deltaCartesian = positionProperty.getValueCartesian(deltaTime, update3DCartesian3Scratch1); if (typeof deltaCartesian !== 'undefined' && !Cartesian3.equalsEpsilon(cartesian, deltaCartesian, CesiumMath.EPSILON6)) { - var toInertial = Transforms.computeFixedToIcrfMatrix(time); - var toInertialDelta = Transforms.computeFixedToIcrfMatrix(deltaTime); - var toFixed = Transforms.computeIcrfToFixedMatrix(time); + var toInertial = Transforms.computeFixedToIcrfMatrix(time, update3DMatrix3Scratch1); + var toInertialDelta = Transforms.computeFixedToIcrfMatrix(deltaTime, update3DMatrix3Scratch2); + var toFixed = Transforms.computeIcrfToFixedMatrix(time, update3DMatrix3Scratch3); // Z along the position - var zBasis = new Cartesian3(); + var zBasis = update3DCartesian3Scratch2; Cartesian3.normalize(cartesian, zBasis); Cartesian3.normalize(deltaCartesian, deltaCartesian); @@ -102,14 +109,10 @@ define([ Matrix3.multiplyByVector(toInertialDelta, deltaCartesian, deltaCartesian); // Y is along the angular momentum vector (e.g. "orbit normal") - var yBasis = Cartesian3.cross(zBasis, deltaCartesian); + var yBasis = Cartesian3.cross(zBasis, deltaCartesian, update3DCartesian3Scratch3); if (!Cartesian3.equalsEpsilon(yBasis, Cartesian3.ZERO, CesiumMath.EPSILON6)) { - Cartesian3.normalize(zBasis, zBasis); - Cartesian3.normalize(yBasis, yBasis); - // X is along the cross of y and z (right handed basis / in the direction of motion) - var xBasis = Cartesian3.cross(yBasis, zBasis); - Cartesian3.normalize(xBasis, xBasis); + var xBasis = Cartesian3.cross(yBasis, zBasis, update3DCartesian3Scratch1); Matrix3.multiplyByVector(toFixed, xBasis, xBasis); Matrix3.multiplyByVector(toFixed, yBasis, yBasis); From be00c3d9f715a7ba5ae9cc139c4a1975f11431b7 Mon Sep 17 00:00:00 2001 From: andre-nunes Date: Fri, 31 May 2013 22:16:12 +0100 Subject: [PATCH 114/306] Replace pseudo-private functions with file-scoped functions --- Source/DynamicScene/DynamicDirectionsProperty.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Source/DynamicScene/DynamicDirectionsProperty.js b/Source/DynamicScene/DynamicDirectionsProperty.js index 01016b5f8885..c0820a9992ba 100644 --- a/Source/DynamicScene/DynamicDirectionsProperty.js +++ b/Source/DynamicScene/DynamicDirectionsProperty.js @@ -95,10 +95,10 @@ define([ DynamicDirectionsProperty.prototype.processCzmlIntervals = function(czmlIntervals, constrainedInterval, dynamicObjectCollection) { if (Array.isArray(czmlIntervals)) { for ( var i = 0, len = czmlIntervals.length; i < len; i++) { - this._addCzmlInterval(czmlIntervals[i], constrainedInterval, dynamicObjectCollection); + addCzmlInterval(this, czmlIntervals[i], constrainedInterval, dynamicObjectCollection); } } else { - this._addCzmlInterval(czmlIntervals, constrainedInterval, dynamicObjectCollection); + addCzmlInterval(this, czmlIntervals, constrainedInterval, dynamicObjectCollection); } }; @@ -132,7 +132,7 @@ define([ return interval.data.getValueCartesian(); }; - DynamicDirectionsProperty.prototype._addCzmlInterval = function(czmlInterval, constrainedInterval, dynamicObjectCollection) { + function addCzmlInterval(dynamicDirectionsProperty, czmlInterval, constrainedInterval, dynamicObjectCollection) { var iso8601Interval = czmlInterval.interval; if (typeof iso8601Interval === 'undefined') { iso8601Interval = Iso8601.MAXIMUM_INTERVAL.clone(); @@ -145,7 +145,7 @@ define([ } //See if we already have data at that interval. - var thisIntervals = this._propertyIntervals; + var thisIntervals = dynamicDirectionsProperty._propertyIntervals; var existingInterval = thisIntervals.findInterval(iso8601Interval.start, iso8601Interval.stop); //If not, create it. @@ -155,7 +155,7 @@ define([ } existingInterval.data = new ValueHolder(czmlInterval); - }; + } return DynamicDirectionsProperty; }); \ No newline at end of file From 712de3286d2583a310f90c7fff0aa21980e7fa7f Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Fri, 31 May 2013 17:18:27 -0400 Subject: [PATCH 115/306] Updates based on review. --- Source/DynamicScene/DynamicObjectView.js | 42 +++++++++++++++--------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/Source/DynamicScene/DynamicObjectView.js b/Source/DynamicScene/DynamicObjectView.js index ff8d969e2eb8..ce5f53827a28 100644 --- a/Source/DynamicScene/DynamicObjectView.js +++ b/Source/DynamicScene/DynamicObjectView.js @@ -77,7 +77,7 @@ define([ } } - var update3DTransform; + var update3DTransform = new Matrix4(); var update3DMatrix3Scratch1 = new Matrix3(); var update3DMatrix3Scratch2 = new Matrix3(); var update3DMatrix3Scratch3 = new Matrix3(); @@ -90,15 +90,16 @@ define([ var cartesian = positionProperty.getValueCartesian(time, that._lastCartesian); if (typeof cartesian !== 'undefined') { - var failed = false; + var successful = false; - var deltaTime = time.addSeconds(1.0); + // The time delta was determined based on how fast satellites move compared to vehicles near the surface. + // Slower moving vehicles will most likely default to east-north-up, while faster ones will be LVLH. + var deltaTime = time.addSeconds(0.01); var deltaCartesian = positionProperty.getValueCartesian(deltaTime, update3DCartesian3Scratch1); if (typeof deltaCartesian !== 'undefined' && !Cartesian3.equalsEpsilon(cartesian, deltaCartesian, CesiumMath.EPSILON6)) { var toInertial = Transforms.computeFixedToIcrfMatrix(time, update3DMatrix3Scratch1); var toInertialDelta = Transforms.computeFixedToIcrfMatrix(deltaTime, update3DMatrix3Scratch2); - var toFixed = Transforms.computeIcrfToFixedMatrix(time, update3DMatrix3Scratch3); - + var toFixed = Matrix3.transpose(toInertial, update3DMatrix3Scratch3); // Z along the position var zBasis = update3DCartesian3Scratch2; @@ -122,19 +123,30 @@ define([ Cartesian3.normalize(yBasis, yBasis); Cartesian3.normalize(zBasis, zBasis); - camera.transform = new Matrix4( - xBasis.x, yBasis.x, zBasis.x, cartesian.x, - xBasis.y, yBasis.y, zBasis.y, cartesian.y, - xBasis.z, yBasis.z, zBasis.z, cartesian.z, - 0.0, 0.0, 0.0, 1.0); - } else { - failed = true; + var transform = update3DTransform; + transform[0] = xBasis.x; + transform[1] = xBasis.y; + transform[2] = xBasis.z; + transform[3] = 0.0; + transform[4] = yBasis.x; + transform[5] = yBasis.y; + transform[6] = yBasis.z; + transform[7] = 0.0; + transform[8] = zBasis.x; + transform[9] = zBasis.y; + transform[10] = zBasis.z; + transform[11] = 0.0; + transform[12] = cartesian.x; + transform[13] = cartesian.y; + transform[14] = cartesian.z; + transform[15] = 0.0; + + camera.transform = transform; + successful = true; } - } else { - failed = true; } - if (failed) { + if (!successful) { camera.transform = Transforms.eastNorthUpToFixedFrame(cartesian, ellipsoid, update3DTransform); } From 20692fab0f3b49011c33793e0bfdcc19a7f9e357 Mon Sep 17 00:00:00 2001 From: Scott Hunter Date: Fri, 31 May 2013 19:48:26 -0400 Subject: [PATCH 116/306] Fix example code in CHANGES.md. Must be indented with a multiple of 4 spaces to be rendered correctly. --- CHANGES.md | 55 +++++++++++++++++++++++++++--------------------------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index f3127ee81e9a..cc648ff5091a 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -62,27 +62,28 @@ Beta Releases * Breaking changes: * Removed the color, outline color, and outline width properties of polylines. Instead, use materials for polyline color and outline properties. Code that looked like: - - var polyline = polylineCollection.add({ - positions : positions, - color : new Color(1.0, 1.0, 1.0, 1.0), - outlineColor : new Color(1.0, 0.0, 0.0, 1.0), - width : 1.0, - outlineWidth : 3.0 - }); - + + var polyline = polylineCollection.add({ + positions : positions, + color : new Color(1.0, 1.0, 1.0, 1.0), + outlineColor : new Color(1.0, 0.0, 0.0, 1.0), + width : 1.0, + outlineWidth : 3.0 + }); + should now look like: - - var outlineMaterial = Material.fromType(context, Material.PolylineOutlineType); - outlineMaterial.uniforms.color = new Color(1.0, 1.0, 1.0, 1.0); - outlineMaterial.uniforms.outlineColor = new Color(1.0, 0.0, 0.0, 1.0); - outlineMaterial.uniforms.outlinewidth = 2.0; - - var polyline = polylineCollection.add({ - positions : positions, - width : 3.0, - material : outlineMaterial - }); + + var outlineMaterial = Material.fromType(context, Material.PolylineOutlineType); + outlineMaterial.uniforms.color = new Color(1.0, 1.0, 1.0, 1.0); + outlineMaterial.uniforms.outlineColor = new Color(1.0, 0.0, 0.0, 1.0); + outlineMaterial.uniforms.outlinewidth = 2.0; + + var polyline = polylineCollection.add({ + positions : positions, + width : 3.0, + material : outlineMaterial + }); + * `CzmlCartographic` has been removed and all cartographic values are converted to Cartesian internally during CZML processing. This improves performance and fixes interpolation of cartographic source data. The Cartographic representation can still be retrieved if needed. * Removed `ComplexConicSensorVolume`, which was not documented and did not work on most platforms. It will be brought back in a future release. This does not affect CZML, which uses a custom sensor to approximate a complex conic. * Replaced `computeSunPosition` with `Simon1994PlanetaryPosition`, which has functions to calculate the position of the sun and the moon more accurately. @@ -108,19 +109,19 @@ Beta Releases * Breaking changes: * `Billboard.computeScreenSpacePosition` now takes `Context` and `FrameState` arguments instead of a `UniformState` argument. * Removed `clampToPixel` property from `BillboardCollection` and `LabelCollection`. This options is no longer be needed due to overall LabelCollection visualization improvements. - * Removed `Widgets/Dojo/CesiumWidget` and replaced it with `Widgets/CesiumWidget`, which has no Dojo dependancies. - * `destroyObject` no longer deletes properties from the object being destroyed. + * Removed `Widgets/Dojo/CesiumWidget` and replaced it with `Widgets/CesiumWidget`, which has no Dojo dependancies. + * `destroyObject` no longer deletes properties from the object being destroyed. * `darker.css` files have been deleted and the `darker` theme is now the default style for widgets. The original theme is now known as `lighter` and is in corresponding `lighter.css` files. * CSS class names have been standardized to avoid potential collisions. All widgets now follow the same pattern, `cesium--`. * Removed `view2D`, `view3D`, and `viewColumbus` properties from `CesiumViewerWidget`. Use the `sceneTransitioner` property instead. * Added `BoundingSphere.fromCornerPoints`. * Added `fromArray` and `distance` functions to `Cartesian2`, `Cartesian3`, and `Cartesian4`. * Added `DynamicPath.resolution` property for setting the maximum step size, in seconds, to take when sampling a position for path visualization. -* Added `TileCoordinatesImageryProvider` that renders imagery with tile X, Y, Level coordinates on the surface of the globe. This is mostly useful for debugging. +* Added `TileCoordinatesImageryProvider` that renders imagery with tile X, Y, Level coordinates on the surface of the globe. This is mostly useful for debugging. * Added `DynamicEllipse` and `DynamicObject.ellipse` property to render CZML ellipses on the globe. * Added `sampleTerrain` function to sample the terrain height of a list of `Cartographic` positions. -* Added `DynamicObjectCollection.removeObject` and handling of the new CZML `delete` property. -* Imagery layers with an `alpha` of exactly 0.0 are no longer rendered. Previously these invisible layers were rendered normally, which was a waste of resources. Unlike the `show` property, imagery tiles in a layer with an `alpha` of 0.0 are still downloaded, so the layer will become visible more quickly when its `alpha` is increased. +* Added `DynamicObjectCollection.removeObject` and handling of the new CZML `delete` property. +* Imagery layers with an `alpha` of exactly 0.0 are no longer rendered. Previously these invisible layers were rendered normally, which was a waste of resources. Unlike the `show` property, imagery tiles in a layer with an `alpha` of 0.0 are still downloaded, so the layer will become visible more quickly when its `alpha` is increased. * Added `onTransitionStart` and `onTransitionComplete` events to `SceneModeTransitioner`. * Added `SceneModePicker`; a new widget for morphing between scene modes. * Added `BaseLayerPicker`; a new widget for switching among pre-configured base layer imagery providers. @@ -136,7 +137,7 @@ Beta Releases * `ClockRange.LOOP` was renamed to `ClockRange.LOOP_STOP` and now only loops in the forward direction. * `Clock.reverseTick` was removed, simply negate `Clock.multiplier` and pass it to `Clock.tick`. * `Clock.shouldAnimate` was added to indicate if `Clock.tick` should actually advance time. - * The Timeline widget was moved into the Widgets/Timeline subdirectory. + * The Timeline widget was moved into the Widgets/Timeline subdirectory. * `Dojo/TimelineWidget` was removed. You should use the non-toolkit specific Timeline widget directly. * Removed `CesiumViewerWidget.fullScreenElement`, instead use the `CesiumViewerWidget.fullscreen.viewModel.fullScreenElement` observable property. * `IntersectionTests.rayPlane` now takes the new `Plane` type instead of separate `planeNormal` and `planeD` arguments. @@ -159,7 +160,7 @@ Beta Releases * The Web Worker files needed when using the combined `Cesium.js` file are now in a `Workers` subdirectory. * Removed `erosion` property from `Polygon`, `ComplexConicSensorVolume`, `RectangularPyramidSensorVolume`, and `ComplexConicSensorVolume`. Use the new `Erosion` material. See the Sandbox Animation example. * Removed `setRectangle` and `getRectangle` methods from `ViewportQuad`. Use the new `rectangle` property. - * Removed `time` parameter from `Scene.initializeFrame`. Instead, pass the time to `Scene.render`. + * Removed `time` parameter from `Scene.initializeFrame`. Instead, pass the time to `Scene.render`. * Added new `RimLighting` and `Erosion` materials. See the [Fabric](https://github.com/AnalyticalGraphicsInc/cesium/wiki/Fabric) wiki page. * Added `hue` and `saturation` properties to `ImageryLayer`. * Added `czm_hue` and `czm_saturation` to adjust the hue and saturation of RGB colors. From 1b6c8c048dd9a92ca4acb061d64302415b7fff5a Mon Sep 17 00:00:00 2001 From: andre-nunes Date: Sat, 1 Jun 2013 01:02:00 +0100 Subject: [PATCH 117/306] Replace pseudo-private functions with file-scoped functions --- .../DynamicBillboardVisualizer.js | 22 ++++++++--------- .../DynamicConeVisualizerUsingCustomSensor.js | 24 +++++++++---------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/Source/DynamicScene/DynamicBillboardVisualizer.js b/Source/DynamicScene/DynamicBillboardVisualizer.js index 403842d8ee97..eeaaefee8dd4 100644 --- a/Source/DynamicScene/DynamicBillboardVisualizer.js +++ b/Source/DynamicScene/DynamicBillboardVisualizer.js @@ -133,7 +133,7 @@ define([ if (typeof this._dynamicObjectCollection !== 'undefined') { var dynamicObjects = this._dynamicObjectCollection.getObjects(); for ( var i = 0, len = dynamicObjects.length; i < len; i++) { - this._updateObject(time, dynamicObjects[i]); + updateObject(this, time, dynamicObjects[i]); } } }; @@ -197,7 +197,7 @@ define([ var color; var eyeOffset; var pixelOffset; - DynamicBillboardVisualizer.prototype._updateObject = function(time, dynamicObject) { + function updateObject(dynamicBillboardVisualizer, time, dynamicObject) { var dynamicBillboard = dynamicObject.billboard; if (typeof dynamicBillboard === 'undefined') { return; @@ -221,26 +221,26 @@ define([ if (!show) { //don't bother creating or updating anything else if (typeof billboardVisualizerIndex !== 'undefined') { - billboard = this._billboardCollection.get(billboardVisualizerIndex); + billboard = dynamicBillboardVisualizer._billboardCollection.get(billboardVisualizerIndex); billboard.setShow(false); billboard.setImageIndex(-1); billboard._visualizerUrl = undefined; billboard._visualizerTextureAvailable = false; dynamicObject._billboardVisualizerIndex = undefined; - this._unusedIndexes.push(billboardVisualizerIndex); + dynamicBillboardVisualizer._unusedIndexes.push(billboardVisualizerIndex); } return; } if (typeof billboardVisualizerIndex === 'undefined') { - var unusedIndexes = this._unusedIndexes; + var unusedIndexes = dynamicBillboardVisualizer._unusedIndexes; var length = unusedIndexes.length; if (length > 0) { billboardVisualizerIndex = unusedIndexes.pop(); - billboard = this._billboardCollection.get(billboardVisualizerIndex); + billboard = dynamicBillboardVisualizer._billboardCollection.get(billboardVisualizerIndex); } else { - billboardVisualizerIndex = this._billboardCollection.getLength(); - billboard = this._billboardCollection.add(); + billboardVisualizerIndex = dynamicBillboardVisualizer._billboardCollection.getLength(); + billboard = dynamicBillboardVisualizer._billboardCollection.add(); } dynamicObject._billboardVisualizerIndex = billboardVisualizerIndex; billboard.dynamicObject = dynamicObject; @@ -255,14 +255,14 @@ define([ billboard.setHorizontalOrigin(HorizontalOrigin.CENTER); billboard.setVerticalOrigin(VerticalOrigin.CENTER); } else { - billboard = this._billboardCollection.get(billboardVisualizerIndex); + billboard = dynamicBillboardVisualizer._billboardCollection.get(billboardVisualizerIndex); } var textureValue = textureProperty.getValue(time); if (textureValue !== billboard._visualizerUrl) { billboard._visualizerUrl = textureValue; billboard._visualizerTextureAvailable = false; - this._textureAtlasBuilder.addTextureFromUrl(textureValue, textureReady(dynamicObject, this._billboardCollection, textureValue)); + dynamicBillboardVisualizer._textureAtlasBuilder.addTextureFromUrl(textureValue, textureReady(dynamicObject, dynamicBillboardVisualizer._billboardCollection, textureValue)); } billboard.setShow(billboard._visualizerTextureAvailable); @@ -323,7 +323,7 @@ define([ billboard.setVerticalOrigin(verticalOrigin); } } - }; + } DynamicBillboardVisualizer.prototype._onObjectsRemoved = function(dynamicObjectCollection, dynamicObjects) { var thisBillboardCollection = this._billboardCollection; diff --git a/Source/DynamicScene/DynamicConeVisualizerUsingCustomSensor.js b/Source/DynamicScene/DynamicConeVisualizerUsingCustomSensor.js index bfb9bcd98d54..cec7b8fa2f3e 100644 --- a/Source/DynamicScene/DynamicConeVisualizerUsingCustomSensor.js +++ b/Source/DynamicScene/DynamicConeVisualizerUsingCustomSensor.js @@ -160,7 +160,7 @@ define([ if (typeof this._dynamicObjectCollection !== 'undefined') { var dynamicObjects = this._dynamicObjectCollection.getObjects(); for ( var i = 0, len = dynamicObjects.length; i < len; i++) { - this._updateObject(time, dynamicObjects[i]); + updateObject(this, time, dynamicObjects[i]); } } }; @@ -228,8 +228,8 @@ define([ var position; var orientation; var intersectionColor; - DynamicConeVisualizerUsingCustomSensor.prototype._updateObject = function(time, dynamicObject) { - var context = this._scene.getContext(); + function updateObject(dynamicConeVisualizerUsingCustomSensor, time, dynamicObject) { + var context = dynamicConeVisualizerUsingCustomSensor._scene.getContext(); var dynamicCone = dynamicObject.cone; if (typeof dynamicCone === 'undefined') { return; @@ -253,26 +253,26 @@ define([ if (!show) { //don't bother creating or updating anything else if (typeof coneVisualizerIndex !== 'undefined') { - cone = this._coneCollection[coneVisualizerIndex]; + cone = dynamicConeVisualizerUsingCustomSensor._coneCollection[coneVisualizerIndex]; cone.show = false; dynamicObject._coneVisualizerIndex = undefined; - this._unusedIndexes.push(coneVisualizerIndex); + dynamicConeVisualizerUsingCustomSensor._unusedIndexes.push(coneVisualizerIndex); } return; } if (typeof coneVisualizerIndex === 'undefined') { - var unusedIndexes = this._unusedIndexes; + var unusedIndexes = dynamicConeVisualizerUsingCustomSensor._unusedIndexes; var length = unusedIndexes.length; if (length > 0) { coneVisualizerIndex = unusedIndexes.pop(); - cone = this._coneCollection[coneVisualizerIndex]; + cone = dynamicConeVisualizerUsingCustomSensor._coneCollection[coneVisualizerIndex]; } else { - coneVisualizerIndex = this._coneCollection.length; + coneVisualizerIndex = dynamicConeVisualizerUsingCustomSensor._coneCollection.length; cone = new CustomSensorVolume(); cone._directionsScratch = []; - this._coneCollection.push(cone); - this._primitives.add(cone); + dynamicConeVisualizerUsingCustomSensor._coneCollection.push(cone); + dynamicConeVisualizerUsingCustomSensor._primitives.add(cone); } dynamicObject._coneVisualizerIndex = coneVisualizerIndex; cone.dynamicObject = dynamicObject; @@ -283,7 +283,7 @@ define([ cone.radius = Number.POSITIVE_INFINITY; cone.showIntersection = true; } else { - cone = this._coneCollection[coneVisualizerIndex]; + cone = dynamicConeVisualizerUsingCustomSensor._coneCollection[coneVisualizerIndex]; } cone.show = true; @@ -368,7 +368,7 @@ define([ cone.intersectionColor = intersectionColor; } } - }; + } DynamicConeVisualizerUsingCustomSensor.prototype._onObjectsRemoved = function(dynamicObjectCollection, dynamicObjects) { var thisConeCollection = this._coneCollection; From 35a0b2e752a3d6f0ce5e404205bca971aa4b33eb Mon Sep 17 00:00:00 2001 From: mramato Date: Fri, 31 May 2013 23:24:41 -0400 Subject: [PATCH 118/306] Update CHANGES --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index cc648ff5091a..e0b3f587a21f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -37,6 +37,7 @@ Beta Releases * `FullscreenWidget` -> `FullscreenButton` * `FullscreenViewModel` -> `FullscreenButtonViewModel` * Removed `addAttribute`, `removeAttribute`, and `setIndexBuffer` from `VertexArray`. They were not used. +* Added support for approximating local vertical, local horizontal (LVLH) reference frames when using `DynamicObjectView` in 3D. The object automatically selects LVLH or EastNorthUp based on the object's velocity. * Added support for CZML defined vectors via new `CzmlDirection`, `DynamicVector`, and `DynamicVectorVisualizer` objects. * Added `SceneTransforms.wgs84ToWindowCoordinates`. [#746](https://github.com/AnalyticalGraphicsInc/cesium/issues/746). * Added `fromElements` to `Cartesian2`, `Cartesian3`, and `Cartesian4`. From 7265a1ba1e75ea7d344b4608b4ffd45589001b32 Mon Sep 17 00:00:00 2001 From: andre-nunes Date: Sat, 1 Jun 2013 13:15:20 +0100 Subject: [PATCH 119/306] Replace pseudo-private functions with file-scoped functions --- .../DynamicEllipsoidVisualizer.js | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Source/DynamicScene/DynamicEllipsoidVisualizer.js b/Source/DynamicScene/DynamicEllipsoidVisualizer.js index a3d2d8c85f82..b1ba109ff9ad 100644 --- a/Source/DynamicScene/DynamicEllipsoidVisualizer.js +++ b/Source/DynamicScene/DynamicEllipsoidVisualizer.js @@ -108,7 +108,7 @@ define([ if (typeof this._dynamicObjectCollection !== 'undefined') { var dynamicObjects = this._dynamicObjectCollection.getObjects(); for ( var i = 0, len = dynamicObjects.length; i < len; i++) { - this._updateObject(time, dynamicObjects[i]); + updateObject(this, time, dynamicObjects[i]); } } }; @@ -175,8 +175,8 @@ define([ var position; var orientation; - DynamicEllipsoidVisualizer.prototype._updateObject = function(time, dynamicObject) { - var context = this._scene.getContext(); + function updateObject(dynamicEllipsoidVisualizer, time, dynamicObject) { + var context = dynamicEllipsoidVisualizer._scene.getContext(); var dynamicEllipsoid = dynamicObject.ellipsoid; if (typeof dynamicEllipsoid === 'undefined') { return; @@ -205,33 +205,33 @@ define([ if (!show) { //don't bother creating or updating anything else if (typeof ellipsoidVisualizerIndex !== 'undefined') { - ellipsoid = this._ellipsoidCollection[ellipsoidVisualizerIndex]; + ellipsoid = dynamicEllipsoidVisualizer._ellipsoidCollection[ellipsoidVisualizerIndex]; ellipsoid.show = false; dynamicObject._ellipsoidVisualizerIndex = undefined; - this._unusedIndexes.push(ellipsoidVisualizerIndex); + dynamicEllipsoidVisualizer._unusedIndexes.push(ellipsoidVisualizerIndex); } return; } if (typeof ellipsoidVisualizerIndex === 'undefined') { - var unusedIndexes = this._unusedIndexes; + var unusedIndexes = dynamicEllipsoidVisualizer._unusedIndexes; var length = unusedIndexes.length; if (length > 0) { ellipsoidVisualizerIndex = unusedIndexes.pop(); - ellipsoid = this._ellipsoidCollection[ellipsoidVisualizerIndex]; + ellipsoid = dynamicEllipsoidVisualizer._ellipsoidCollection[ellipsoidVisualizerIndex]; } else { - ellipsoidVisualizerIndex = this._ellipsoidCollection.length; + ellipsoidVisualizerIndex = dynamicEllipsoidVisualizer._ellipsoidCollection.length; ellipsoid = new EllipsoidPrimitive(); - this._ellipsoidCollection.push(ellipsoid); - this._primitives.add(ellipsoid); + dynamicEllipsoidVisualizer._ellipsoidCollection.push(ellipsoid); + dynamicEllipsoidVisualizer._primitives.add(ellipsoid); } dynamicObject._ellipsoidVisualizerIndex = ellipsoidVisualizerIndex; ellipsoid.dynamicObject = dynamicObject; ellipsoid.material = Material.fromType(context, Material.ColorType); } else { - ellipsoid = this._ellipsoidCollection[ellipsoidVisualizerIndex]; + ellipsoid = dynamicEllipsoidVisualizer._ellipsoidCollection[ellipsoidVisualizerIndex]; } ellipsoid.show = true; @@ -254,7 +254,7 @@ define([ if (typeof material !== 'undefined') { ellipsoid.material = material.getValue(time, context, ellipsoid.material); } - }; + } DynamicEllipsoidVisualizer.prototype._onObjectsRemoved = function(dynamicObjectCollection, dynamicObjects) { var thisEllipsoidCollection = this._ellipsoidCollection; From 857743166c4d6de566982097b32c6a5cd6ee5501 Mon Sep 17 00:00:00 2001 From: andre-nunes Date: Sat, 1 Jun 2013 13:22:12 +0100 Subject: [PATCH 120/306] Replace pseudo-private functions with file-scoped functions --- Source/DynamicScene/DynamicLabelVisualizer.js | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Source/DynamicScene/DynamicLabelVisualizer.js b/Source/DynamicScene/DynamicLabelVisualizer.js index 95d9570fca48..9ba92e94e4de 100644 --- a/Source/DynamicScene/DynamicLabelVisualizer.js +++ b/Source/DynamicScene/DynamicLabelVisualizer.js @@ -112,7 +112,7 @@ define([ if (typeof this._dynamicObjectCollection !== 'undefined') { var dynamicObjects = this._dynamicObjectCollection.getObjects(); for ( var i = 0, len = dynamicObjects.length; i < len; i++) { - this._updateObject(time, dynamicObjects[i]); + updateObject(this, time, dynamicObjects[i]); } } }; @@ -177,7 +177,7 @@ define([ var outlineColor; var eyeOffset; var pixelOffset; - DynamicLabelVisualizer.prototype._updateObject = function(time, dynamicObject) { + function updateObject(dynamicLabelVisualizer, time, dynamicObject) { var dynamicLabel = dynamicObject.label; if (typeof dynamicLabel === 'undefined') { return; @@ -201,23 +201,23 @@ define([ if (!show) { //don't bother creating or updating anything else if (typeof labelVisualizerIndex !== 'undefined') { - label = this._labelCollection.get(labelVisualizerIndex); + label = dynamicLabelVisualizer._labelCollection.get(labelVisualizerIndex); label.setShow(false); - this._unusedIndexes.push(labelVisualizerIndex); + dynamicLabelVisualizer._unusedIndexes.push(labelVisualizerIndex); dynamicObject._labelVisualizerIndex = undefined; } return; } if (typeof labelVisualizerIndex === 'undefined') { - var unusedIndexes = this._unusedIndexes; + var unusedIndexes = dynamicLabelVisualizer._unusedIndexes; var length = unusedIndexes.length; if (length > 0) { labelVisualizerIndex = unusedIndexes.pop(); - label = this._labelCollection.get(labelVisualizerIndex); + label = dynamicLabelVisualizer._labelCollection.get(labelVisualizerIndex); } else { - labelVisualizerIndex = this._labelCollection.getLength(); - label = this._labelCollection.add(); + labelVisualizerIndex = dynamicLabelVisualizer._labelCollection.getLength(); + label = dynamicLabelVisualizer._labelCollection.add(); } dynamicObject._labelVisualizerIndex = labelVisualizerIndex; label.dynamicObject = dynamicObject; @@ -235,7 +235,7 @@ define([ label.setHorizontalOrigin(HorizontalOrigin.CENTER); label.setVerticalOrigin(VerticalOrigin.CENTER); } else { - label = this._labelCollection.get(labelVisualizerIndex); + label = dynamicLabelVisualizer._labelCollection.get(labelVisualizerIndex); } label.setShow(show); @@ -329,7 +329,7 @@ define([ label.setVerticalOrigin(verticalOrigin); } } - }; + } DynamicLabelVisualizer.prototype._onObjectsRemoved = function(dynamicObjectCollection, dynamicObjects) { var thisLabelCollection = this._labelCollection; From 33fa66feeb97c88b977281a0239f68be0d825ace Mon Sep 17 00:00:00 2001 From: andre-nunes Date: Sat, 1 Jun 2013 13:26:58 +0100 Subject: [PATCH 121/306] Replace pseudo-private functions with file-scoped functions --- Source/DynamicScene/DynamicMaterialProperty.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Source/DynamicScene/DynamicMaterialProperty.js b/Source/DynamicScene/DynamicMaterialProperty.js index bd221b403bb0..10bea9b181ba 100644 --- a/Source/DynamicScene/DynamicMaterialProperty.js +++ b/Source/DynamicScene/DynamicMaterialProperty.js @@ -49,10 +49,10 @@ define([ DynamicMaterialProperty.prototype.processCzmlIntervals = function(czmlIntervals, constrainedInterval, sourceUri) { if (Array.isArray(czmlIntervals)) { for ( var i = 0, len = czmlIntervals.length; i < len; i++) { - this._addCzmlInterval(czmlIntervals[i], constrainedInterval, sourceUri); + addCzmlInterval(this, czmlIntervals[i], constrainedInterval, sourceUri); } } else { - this._addCzmlInterval(czmlIntervals, constrainedInterval, sourceUri); + addCzmlInterval(this, czmlIntervals, constrainedInterval, sourceUri); } }; @@ -74,7 +74,7 @@ define([ return existingMaterial; }; - DynamicMaterialProperty.prototype._addCzmlInterval = function(czmlInterval, constrainedInterval, sourceUri) { + function addCzmlInterval(dynamicMaterialProperty, czmlInterval, constrainedInterval, sourceUri) { var iso8601Interval = czmlInterval.interval; if (typeof iso8601Interval === 'undefined') { iso8601Interval = Iso8601.MAXIMUM_INTERVAL.clone(); @@ -87,7 +87,7 @@ define([ } //See if we already have data at that interval. - var thisIntervals = this._intervals; + var thisIntervals = dynamicMaterialProperty._intervals; var existingInterval = thisIntervals.findInterval(iso8601Interval.start, iso8601Interval.stop); var foundMaterial = false; var existingMaterial; @@ -119,7 +119,7 @@ define([ if (foundMaterial) { existingMaterial.processCzmlIntervals(czmlInterval, sourceUri); } - }; + } return DynamicMaterialProperty; }); \ No newline at end of file From bccc55cef13f439b35fa2bcd6be560113714cbe1 Mon Sep 17 00:00:00 2001 From: andre-nunes Date: Sat, 1 Jun 2013 14:19:37 +0100 Subject: [PATCH 122/306] Replace pseudo-private functions with file-scoped functions --- Source/DynamicScene/DynamicPointVisualizer.js | 22 ++++++++--------- .../DynamicScene/DynamicPolygonVisualizer.js | 24 +++++++++---------- .../DynamicScene/DynamicPolylineVisualizer.js | 22 ++++++++--------- 3 files changed, 34 insertions(+), 34 deletions(-) diff --git a/Source/DynamicScene/DynamicPointVisualizer.js b/Source/DynamicScene/DynamicPointVisualizer.js index be31ffea9ec1..e73a87c41ebf 100644 --- a/Source/DynamicScene/DynamicPointVisualizer.js +++ b/Source/DynamicScene/DynamicPointVisualizer.js @@ -108,7 +108,7 @@ define([ if (typeof this._dynamicObjectCollection !== 'undefined') { var dynamicObjects = this._dynamicObjectCollection.getObjects(); for ( var i = 0, len = dynamicObjects.length; i < len; i++) { - this._updateObject(time, dynamicObjects[i]); + updateObject(this, time, dynamicObjects[i]); } } }; @@ -171,7 +171,7 @@ define([ var color; var position; var outlineColor; - DynamicPointVisualizer.prototype._updateObject = function(time, dynamicObject) { + function updateObject(dynamicPointVisualizer, time, dynamicObject) { var dynamicPoint = dynamicObject.point; if (typeof dynamicPoint === 'undefined') { return; @@ -190,25 +190,25 @@ define([ if (!show) { //don't bother creating or updating anything else if (typeof pointVisualizerIndex !== 'undefined') { - billboard = this._billboardCollection.get(pointVisualizerIndex); + billboard = dynamicPointVisualizer._billboardCollection.get(pointVisualizerIndex); billboard.setShow(false); billboard.setImageIndex(-1); dynamicObject._pointVisualizerIndex = undefined; - this._unusedIndexes.push(pointVisualizerIndex); + dynamicPointVisualizer._unusedIndexes.push(pointVisualizerIndex); } return; } var needRedraw = false; if (typeof pointVisualizerIndex === 'undefined') { - var unusedIndexes = this._unusedIndexes; + var unusedIndexes = dynamicPointVisualizer._unusedIndexes; var length = unusedIndexes.length; if (length > 0) { pointVisualizerIndex = unusedIndexes.pop(); - billboard = this._billboardCollection.get(pointVisualizerIndex); + billboard = dynamicPointVisualizer._billboardCollection.get(pointVisualizerIndex); } else { - pointVisualizerIndex = this._billboardCollection.getLength(); - billboard = this._billboardCollection.add(); + pointVisualizerIndex = dynamicPointVisualizer._billboardCollection.getLength(); + billboard = dynamicPointVisualizer._billboardCollection.add(); } dynamicObject._pointVisualizerIndex = pointVisualizerIndex; billboard.dynamicObject = dynamicObject; @@ -220,7 +220,7 @@ define([ billboard._visualizerPixelSize = 1; needRedraw = true; } else { - billboard = this._billboardCollection.get(pointVisualizerIndex); + billboard = dynamicPointVisualizer._billboardCollection.get(pointVisualizerIndex); } billboard.setShow(true); @@ -273,7 +273,7 @@ define([ var cssOutlineWidth = defaultValue(billboard._visualizerOutlineWidth, 2); var textureId = JSON.stringify([cssColor, cssPixelSize, cssOutlineColor, cssOutlineWidth]); - this._textureAtlasBuilder.addTextureFromFunction(textureId, function(id, loadedCallback) { + dynamicPointVisualizer._textureAtlasBuilder.addTextureFromFunction(textureId, function(id, loadedCallback) { var canvas = document.createElement('canvas'); var length = cssPixelSize + (2 * cssOutlineWidth); @@ -301,7 +301,7 @@ define([ billboard.setImageIndex(imageIndex); }); } - }; + } DynamicPointVisualizer.prototype._onObjectsRemoved = function(dynamicObjectCollection, dynamicObjects) { var thisBillboardCollection = this._billboardCollection; diff --git a/Source/DynamicScene/DynamicPolygonVisualizer.js b/Source/DynamicScene/DynamicPolygonVisualizer.js index b7ede0ade4ba..dc9515ac69ef 100644 --- a/Source/DynamicScene/DynamicPolygonVisualizer.js +++ b/Source/DynamicScene/DynamicPolygonVisualizer.js @@ -102,7 +102,7 @@ define(['../Core/Cartesian3', if (typeof this._dynamicObjectCollection !== 'undefined') { var dynamicObjects = this._dynamicObjectCollection.getObjects(); for ( var i = 0, len = dynamicObjects.length; i < len; i++) { - this._updateObject(time, dynamicObjects[i]); + updateObject(this, time, dynamicObjects[i]); } } }; @@ -168,7 +168,7 @@ define(['../Core/Cartesian3', }; var cachedPosition = new Cartesian3(); - DynamicPolygonVisualizer.prototype._updateObject = function(time, dynamicObject) { + function updateObject(dynamicPolygonVisualizer, time, dynamicObject) { var dynamicPolygon = dynamicObject.polygon; if (typeof dynamicPolygon === 'undefined') { return; @@ -187,26 +187,26 @@ define(['../Core/Cartesian3', (typeof ellipseProperty === 'undefined' || typeof positionProperty === 'undefined'))) { //Remove the existing primitive if we have one if (typeof polygonVisualizerIndex !== 'undefined') { - polygon = this._polygonCollection[polygonVisualizerIndex]; + polygon = dynamicPolygonVisualizer._polygonCollection[polygonVisualizerIndex]; polygon.show = false; dynamicObject._polygonVisualizerIndex = undefined; - this._unusedIndexes.push(polygonVisualizerIndex); + dynamicPolygonVisualizer._unusedIndexes.push(polygonVisualizerIndex); } return; } - var context = this._scene.getContext(); + var context = dynamicPolygonVisualizer._scene.getContext(); if (typeof polygonVisualizerIndex === 'undefined') { - var unusedIndexes = this._unusedIndexes; + var unusedIndexes = dynamicPolygonVisualizer._unusedIndexes; var length = unusedIndexes.length; if (length > 0) { polygonVisualizerIndex = unusedIndexes.pop(); - polygon = this._polygonCollection[polygonVisualizerIndex]; + polygon = dynamicPolygonVisualizer._polygonCollection[polygonVisualizerIndex]; } else { - polygonVisualizerIndex = this._polygonCollection.length; + polygonVisualizerIndex = dynamicPolygonVisualizer._polygonCollection.length; polygon = new Polygon(); - this._polygonCollection.push(polygon); - this._primitives.add(polygon); + dynamicPolygonVisualizer._polygonCollection.push(polygon); + dynamicPolygonVisualizer._primitives.add(polygon); } dynamicObject._polygonVisualizerIndex = polygonVisualizerIndex; polygon.dynamicObject = dynamicObject; @@ -214,7 +214,7 @@ define(['../Core/Cartesian3', // CZML_TODO Determine official defaults polygon.material = Material.fromType(context, Material.ColorType); } else { - polygon = this._polygonCollection[polygonVisualizerIndex]; + polygon = dynamicPolygonVisualizer._polygonCollection[polygonVisualizerIndex]; } polygon.show = true; @@ -237,7 +237,7 @@ define(['../Core/Cartesian3', if (typeof material !== 'undefined') { polygon.material = material.getValue(time, context, polygon.material); } - }; + } DynamicPolygonVisualizer.prototype._onObjectsRemoved = function(dynamicObjectCollection, dynamicObjects) { var thisPolygonCollection = this._polygonCollection; diff --git a/Source/DynamicScene/DynamicPolylineVisualizer.js b/Source/DynamicScene/DynamicPolylineVisualizer.js index 3e80aa8f152d..7ed7a4a00ba9 100644 --- a/Source/DynamicScene/DynamicPolylineVisualizer.js +++ b/Source/DynamicScene/DynamicPolylineVisualizer.js @@ -106,7 +106,7 @@ define([ if (typeof this._dynamicObjectCollection !== 'undefined') { var dynamicObjects = this._dynamicObjectCollection.getObjects(); for ( var i = 0, len = dynamicObjects.length; i < len; i++) { - this._updateObject(time, dynamicObjects[i]); + updateObject(this, time, dynamicObjects[i]); } } }; @@ -170,7 +170,7 @@ define([ }; var cachedPosition = new Cartesian3(); - DynamicPolylineVisualizer.prototype._updateObject = function(time, dynamicObject) { + function updateObject(dynamicPolylineVisualizer, time, dynamicObject) { var dynamicPolyline = dynamicObject.polyline; if (typeof dynamicPolyline === 'undefined') { return; @@ -189,24 +189,24 @@ define([ (typeof ellipseProperty === 'undefined' || typeof positionProperty === 'undefined'))) { //Remove the existing primitive if we have one if (typeof polylineVisualizerIndex !== 'undefined') { - polyline = this._polylineCollection.get(polylineVisualizerIndex); + polyline = dynamicPolylineVisualizer._polylineCollection.get(polylineVisualizerIndex); polyline.setShow(false); dynamicObject._polylineVisualizerIndex = undefined; - this._unusedIndexes.push(polylineVisualizerIndex); + dynamicPolylineVisualizer._unusedIndexes.push(polylineVisualizerIndex); } return; } var uniforms; if (typeof polylineVisualizerIndex === 'undefined') { - var unusedIndexes = this._unusedIndexes; + var unusedIndexes = dynamicPolylineVisualizer._unusedIndexes; var length = unusedIndexes.length; if (length > 0) { polylineVisualizerIndex = unusedIndexes.pop(); - polyline = this._polylineCollection.get(polylineVisualizerIndex); + polyline = dynamicPolylineVisualizer._polylineCollection.get(polylineVisualizerIndex); } else { - polylineVisualizerIndex = this._polylineCollection.getLength(); - polyline = this._polylineCollection.add(); + polylineVisualizerIndex = dynamicPolylineVisualizer._polylineCollection.getLength(); + polyline = dynamicPolylineVisualizer._polylineCollection.add(); } dynamicObject._polylineVisualizerIndex = polylineVisualizerIndex; polyline.dynamicObject = dynamicObject; @@ -215,7 +215,7 @@ define([ polyline.setWidth(1); var material = polyline.getMaterial(); if (typeof material === 'undefined' || (material.type !== Material.PolylineOutlineType)) { - material = Material.fromType(this._scene.getContext(), Material.PolylineOutlineType); + material = Material.fromType(dynamicPolylineVisualizer._scene.getContext(), Material.PolylineOutlineType); polyline.setMaterial(material); } uniforms = material.uniforms; @@ -223,7 +223,7 @@ define([ Color.clone(Color.BLACK, uniforms.outlineColor); uniforms.outlineWidth = 0; } else { - polyline = this._polylineCollection.get(polylineVisualizerIndex); + polyline = dynamicPolylineVisualizer._polylineCollection.get(polylineVisualizerIndex); uniforms = polyline.getMaterial().uniforms; } @@ -263,7 +263,7 @@ define([ polyline.setWidth(width); } } - }; + } DynamicPolylineVisualizer.prototype._onObjectsRemoved = function(dynamicObjectCollection, dynamicObjects) { var thisPolylineCollection = this._polylineCollection; From c74a76735e28823a7d5622ba0d89524c55e79192 Mon Sep 17 00:00:00 2001 From: andre-nunes Date: Mon, 3 Jun 2013 00:46:12 +0100 Subject: [PATCH 123/306] Replace pseudo-private functions with file-scoped functions --- .../DynamicScene/DynamicPyramidVisualizer.js | 24 +++++++++---------- .../DynamicScene/DynamicVectorVisualizer.js | 22 ++++++++--------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/Source/DynamicScene/DynamicPyramidVisualizer.js b/Source/DynamicScene/DynamicPyramidVisualizer.js index d134865337e3..c43feff4221d 100644 --- a/Source/DynamicScene/DynamicPyramidVisualizer.js +++ b/Source/DynamicScene/DynamicPyramidVisualizer.js @@ -111,7 +111,7 @@ define([ if (typeof this._dynamicObjectCollection !== 'undefined') { var dynamicObjects = this._dynamicObjectCollection.getObjects(); for ( var i = 0, len = dynamicObjects.length; i < len; i++) { - this._updateObject(time, dynamicObjects[i]); + updateObject(this, time, dynamicObjects[i]); } } }; @@ -178,8 +178,8 @@ define([ var position; var orientation; - DynamicPyramidVisualizer.prototype._updateObject = function(time, dynamicObject) { - var context = this._scene.getContext(); + function updateObject(dynamicPyramidVisualizer, time, dynamicObject) { + var context = dynamicPyramidVisualizer._scene.getContext(); var dynamicPyramid = dynamicObject.pyramid; if (typeof dynamicPyramid === 'undefined') { return; @@ -208,26 +208,26 @@ define([ if (!show) { //don't bother creating or updating anything else if (typeof pyramidVisualizerIndex !== 'undefined') { - pyramid = this._pyramidCollection[pyramidVisualizerIndex]; + pyramid = dynamicPyramidVisualizer._pyramidCollection[pyramidVisualizerIndex]; pyramid.show = false; dynamicObject._pyramidVisualizerIndex = undefined; - this._unusedIndexes.push(pyramidVisualizerIndex); + dynamicPyramidVisualizer._unusedIndexes.push(pyramidVisualizerIndex); } return; } if (typeof pyramidVisualizerIndex === 'undefined') { - var unusedIndexes = this._unusedIndexes; + var unusedIndexes = dynamicPyramidVisualizer._unusedIndexes; var length = unusedIndexes.length; if (length > 0) { pyramidVisualizerIndex = unusedIndexes.pop(); - pyramid = this._pyramidCollection[pyramidVisualizerIndex]; + pyramid = dynamicPyramidVisualizer._pyramidCollection[pyramidVisualizerIndex]; } else { - pyramidVisualizerIndex = this._pyramidCollection.length; + pyramidVisualizerIndex = dynamicPyramidVisualizer._pyramidCollection.length; pyramid = new CustomSensorVolume(); - this._pyramidCollection.push(pyramid); - this._primitives.add(pyramid); + dynamicPyramidVisualizer._pyramidCollection.push(pyramid); + dynamicPyramidVisualizer._primitives.add(pyramid); } dynamicObject._pyramidVisualizerIndex = pyramidVisualizerIndex; pyramid.dynamicObject = dynamicObject; @@ -238,7 +238,7 @@ define([ pyramid.intersectionColor = Color.YELLOW; pyramid.material = Material.fromType(context, Material.ColorType); } else { - pyramid = this._pyramidCollection[pyramidVisualizerIndex]; + pyramid = dynamicPyramidVisualizer._pyramidCollection[pyramidVisualizerIndex]; } pyramid.show = true; @@ -281,7 +281,7 @@ define([ pyramid.radius = radius; } } - }; + } DynamicPyramidVisualizer.prototype._onObjectsRemoved = function(dynamicObjectCollection, dynamicObjects) { var thisPyramidCollection = this._pyramidCollection; diff --git a/Source/DynamicScene/DynamicVectorVisualizer.js b/Source/DynamicScene/DynamicVectorVisualizer.js index e3352a7db205..3b79c40b5e28 100644 --- a/Source/DynamicScene/DynamicVectorVisualizer.js +++ b/Source/DynamicScene/DynamicVectorVisualizer.js @@ -106,7 +106,7 @@ define([ if (typeof this._dynamicObjectCollection !== 'undefined') { var dynamicObjects = this._dynamicObjectCollection.getObjects(); for ( var i = 0, len = dynamicObjects.length; i < len; i++) { - this._updateObject(time, dynamicObjects[i]); + updateObject(this, time, dynamicObjects[i]); } } }; @@ -169,7 +169,7 @@ define([ return destroyObject(this); }; - DynamicVectorVisualizer.prototype._updateObject = function(time, dynamicObject) { + function updateObject(dynamicVectorVisualizer, time, dynamicObject) { var dynamicVector = dynamicObject.vector; if (typeof dynamicVector === 'undefined') { return; @@ -187,23 +187,23 @@ define([ (typeof directionProperty === 'undefined' || typeof positionProperty === 'undefined' || typeof lengthProperty === 'undefined')) { //Remove the existing primitive if we have one if (typeof vectorVisualizerIndex !== 'undefined') { - polyline = this._polylineCollection.get(vectorVisualizerIndex); + polyline = dynamicVectorVisualizer._polylineCollection.get(vectorVisualizerIndex); polyline.setShow(false); dynamicObject._vectorVisualizerIndex = undefined; - this._unusedIndexes.push(vectorVisualizerIndex); + dynamicVectorVisualizer._unusedIndexes.push(vectorVisualizerIndex); } return; } var uniforms; if (typeof vectorVisualizerIndex === 'undefined') { - var unusedIndexes = this._unusedIndexes; + var unusedIndexes = dynamicVectorVisualizer._unusedIndexes; if (unusedIndexes.length > 0) { vectorVisualizerIndex = unusedIndexes.pop(); - polyline = this._polylineCollection.get(vectorVisualizerIndex); + polyline = dynamicVectorVisualizer._polylineCollection.get(vectorVisualizerIndex); } else { - vectorVisualizerIndex = this._polylineCollection.getLength(); - polyline = this._polylineCollection.add(); + vectorVisualizerIndex = dynamicVectorVisualizer._polylineCollection.getLength(); + polyline = dynamicVectorVisualizer._polylineCollection.add(); polyline._visualizerPositions = [new Cartesian3(), new Cartesian3()]; } dynamicObject._vectorVisualizerIndex = vectorVisualizerIndex; @@ -213,13 +213,13 @@ define([ polyline.setWidth(1); var material = polyline.getMaterial(); if (typeof material === 'undefined' || (material.type !== Material.PolylineArrowType)) { - material = Material.fromType(this._scene.getContext(), Material.PolylineArrowType); + material = Material.fromType(dynamicVectorVisualizer._scene.getContext(), Material.PolylineArrowType); polyline.setMaterial(material); } uniforms = material.uniforms; Color.clone(Color.WHITE, uniforms.color); } else { - polyline = this._polylineCollection.get(vectorVisualizerIndex); + polyline = dynamicVectorVisualizer._polylineCollection.get(vectorVisualizerIndex); uniforms = polyline.getMaterial().uniforms; } @@ -246,7 +246,7 @@ define([ polyline.setWidth(width); } } - }; + } DynamicVectorVisualizer.prototype._onObjectsRemoved = function(dynamicObjectCollection, dynamicObjects) { var thisPolylineCollection = this._polylineCollection; From 45886e5e9a4a6053989467bbc4e606cd647b78c9 Mon Sep 17 00:00:00 2001 From: andre-nunes Date: Mon, 3 Jun 2013 00:54:35 +0100 Subject: [PATCH 124/306] Replace pseudo-private functions with file-scoped functions --- .../CompositeDynamicObjectCollection.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Source/DynamicScene/CompositeDynamicObjectCollection.js b/Source/DynamicScene/CompositeDynamicObjectCollection.js index f666a852e48a..bea3f01794c8 100644 --- a/Source/DynamicScene/CompositeDynamicObjectCollection.js +++ b/Source/DynamicScene/CompositeDynamicObjectCollection.js @@ -136,7 +136,7 @@ define([ thisCollections = this._collections = collections; //Clear all existing objects and rebuild the collection. - this._clearObjects(); + clearObjects(this); var thisMergeFunctions = this.mergeFunctions; for (iCollection = thisCollections.length - 1; iCollection > -1; iCollection--) { collection = thisCollections[iCollection]; @@ -203,14 +203,14 @@ define([ return obj; } - CompositeDynamicObjectCollection.prototype._clearObjects = function() { - var removedObjects = this._array; - this._hash = {}; - this._array = []; + function clearObjects(compositeDynamicObjectCollection) { + var removedObjects = compositeDynamicObjectCollection._array; + compositeDynamicObjectCollection._hash = {}; + compositeDynamicObjectCollection._array = []; if (removedObjects.length > 0) { - this.objectsRemoved.raiseEvent(this, removedObjects); + compositeDynamicObjectCollection.objectsRemoved.raiseEvent(compositeDynamicObjectCollection, removedObjects); } - }; + } CompositeDynamicObjectCollection.prototype._onObjectPropertiesChanged = function(dynamicObjectCollection, updatedObjects) { var thisMergeFunctions = this.mergeFunctions; From 808bf3697ab60263cabb01550291b4c406ea2c99 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 3 Jun 2013 13:50:44 -0400 Subject: [PATCH 125/306] Updates after review. --- Source/Core/WallGeometry.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Source/Core/WallGeometry.js b/Source/Core/WallGeometry.js index ef8f1d94a9f3..811f39059025 100644 --- a/Source/Core/WallGeometry.js +++ b/Source/Core/WallGeometry.js @@ -94,11 +94,11 @@ define([ var i; var size = wallPositions.length * 2; - var positions = (vertexFormat.position) ? new Array(size * 3) : undefined; - var normals = (vertexFormat.normal) ? new Array(size * 3) : undefined; - var tangents = (vertexFormat.tangent) ? new Array(size * 3) : undefined; - var binormals = (vertexFormat.binormal) ? new Array(size * 3) : undefined; - var textureCoordinates = (vertexFormat.st) ? new Array(size * 2) : undefined; + var positions = vertexFormat.position ? new Array(size * 3) : undefined; + var normals = vertexFormat.normal ? new Array(size * 3) : undefined; + var tangents = vertexFormat.tangent ? new Array(size * 3) : undefined; + var binormals = vertexFormat.binormal ? new Array(size * 3) : undefined; + var textureCoordinates = vertexFormat.st ? new Array(size * 2) : undefined; var positionIndex = 0; var normalIndex = 0; From 22538936ee4db003767822c2e2a88c79346fca07 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 3 Jun 2013 14:39:34 -0400 Subject: [PATCH 126/306] Update wall Sandcastle example and add temporary wall to CesiumViewer for testing. --- Apps/CesiumViewer/CesiumViewer.js | 28 ++++++++++++++++++++++++++++ Apps/Sandcastle/gallery/Wall.html | 3 --- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index d353ee26723c..62c165f72e54 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -22,6 +22,8 @@ define([ 'Core/Transforms', 'Core/ScreenSpaceEventHandler', 'Core/ScreenSpaceEventType', + 'Core/WallGeometry', + 'Renderer/BlendingState', 'Scene/Primitive', 'Scene/Appearance', 'Scene/Material', @@ -50,6 +52,8 @@ define([ Transforms, ScreenSpaceEventHandler, ScreenSpaceEventType, + WallGeometry, + BlendingState, Primitive, Appearance, Material, @@ -221,6 +225,30 @@ define([ appearance : Appearance.CLOSED_TRANSLUCENT })); + var wall = new WallGeometry({ + positions : ellipsoid.cartographicArrayToCartesianArray([ + Cartographic.fromDegrees(-125.0, 37.0, 100000.0), + Cartographic.fromDegrees(-125.0, 38.0, 100000.0), + Cartographic.fromDegrees(-120.0, 38.0, 100000.0), + Cartographic.fromDegrees(-120.0, 37.0, 100000.0), + Cartographic.fromDegrees(-125.0, 37.0, 100000.0) + ]), + pickData : 'wall' + }); + var wallAppearance = new Appearance({ + renderState : { + depthTest : { + enabled : true + }, + depthMask : false, + blending : BlendingState.ALPHA_BLEND + } + }); + widget.scene.getPrimitives().add(new Primitive({ + geometries : wall, + appearance : wallAppearance + })); + var handler = new ScreenSpaceEventHandler(scene.getCanvas()); handler.setInputAction( function (movement) { diff --git a/Apps/Sandcastle/gallery/Wall.html b/Apps/Sandcastle/gallery/Wall.html index a10a97e7ff37..d3a0443b20bd 100644 --- a/Apps/Sandcastle/gallery/Wall.html +++ b/Apps/Sandcastle/gallery/Wall.html @@ -81,7 +81,6 @@ // create a wall that spans from ground level to 10000 meters var wall1 = new Cesium.WallGeometry({ - altitudeMode : 'absolute', positions : ellipsoid.cartographicArrayToCartesianArray(positions), pickData : 'wall1' }); @@ -95,7 +94,6 @@ // create a wall with the same coordinates, but from 15000 - 25000 meters var wall2 = new Cesium.WallGeometry({ - altitudeMode : 'absolute', positions : ellipsoid.cartographicArrayToCartesianArray(positions), bottom : 15000, top : 25000, @@ -126,7 +124,6 @@ Cesium.when(Cesium.sampleTerrain(terrainProvider, 11, t), function(terrain) { var wall3 = new Cesium.WallGeometry({ - altitudeMode : 'relativeToGround', positions : ellipsoid.cartographicArrayToCartesianArray(positions), terrain : terrain, pickData : 'wall3' From ff24457d28e33724653fb1b6ae087bab0598d745 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Mon, 3 Jun 2013 14:57:32 -0400 Subject: [PATCH 127/306] Added EllipsoidSurface appearance --- Apps/CesiumViewer/CesiumViewer.js | 69 +++++---- Source/Core/ExtentGeometry.js | 6 +- Source/Core/PolygonGeometry.js | 145 ++++++++++++++++-- Source/Core/VertexFormat.js | 10 ++ Source/Scene/Appearance.js | 27 +++- Source/Scene/Polygon.js | 1 + .../EllipsoidSurfaceAppearanceFS.glsl | 25 +++ .../EllipsoidSurfaceAppearanceVS.glsl | 21 +++ 8 files changed, 258 insertions(+), 46 deletions(-) create mode 100644 Source/Shaders/Appearances/EllipsoidSurfaceAppearanceFS.glsl create mode 100644 Source/Shaders/Appearances/EllipsoidSurfaceAppearanceVS.glsl diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index d353ee26723c..b8485ad4322d 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -181,44 +181,59 @@ define([ scene.getPrimitives().add(primitive2); var polygonGeometry = new PolygonGeometry({ - polygonHierarchy : { + vertexFormat : VertexFormat.POSITION_AND_ST, +/* + positions : ellipsoid.cartographicArrayToCartesianArray([ + Cartographic.fromDegrees(-72.0, 40.0), + Cartographic.fromDegrees(-70.0, 35.0), + Cartographic.fromDegrees(-75.0, 30.0), + Cartographic.fromDegrees(-70.0, 30.0), + Cartographic.fromDegrees(-68.0, 40.0) + ]), +*/ + + polygonHierarchy : { + positions : ellipsoid.cartographicArrayToCartesianArray([ + Cartographic.fromDegrees(-109.0, 30.0), + Cartographic.fromDegrees(-95.0, 30.0), + Cartographic.fromDegrees(-95.0, 40.0), + Cartographic.fromDegrees(-109.0, 40.0) + ]), + holes : [{ positions : ellipsoid.cartographicArrayToCartesianArray([ - Cartographic.fromDegrees(-109.0, 30.0), - Cartographic.fromDegrees(-95.0, 30.0), - Cartographic.fromDegrees(-95.0, 40.0), - Cartographic.fromDegrees(-109.0, 40.0) + Cartographic.fromDegrees(-107.0, 31.0), + Cartographic.fromDegrees(-107.0, 39.0), + Cartographic.fromDegrees(-97.0, 39.0), + Cartographic.fromDegrees(-97.0, 31.0) ]), holes : [{ positions : ellipsoid.cartographicArrayToCartesianArray([ - Cartographic.fromDegrees(-107.0, 31.0), - Cartographic.fromDegrees(-107.0, 39.0), - Cartographic.fromDegrees(-97.0, 39.0), - Cartographic.fromDegrees(-97.0, 31.0) - ]), + Cartographic.fromDegrees(-105.0, 33.0), + Cartographic.fromDegrees(-99.0, 33.0), + Cartographic.fromDegrees(-99.0, 37.0), + Cartographic.fromDegrees(-105.0, 37.0) + ]), holes : [{ positions : ellipsoid.cartographicArrayToCartesianArray([ - Cartographic.fromDegrees(-105.0, 33.0), - Cartographic.fromDegrees(-99.0, 33.0), - Cartographic.fromDegrees(-99.0, 37.0), - Cartographic.fromDegrees(-105.0, 37.0) - ]), - holes : [{ - positions : ellipsoid.cartographicArrayToCartesianArray([ - Cartographic.fromDegrees(-103.0, 34.0), - Cartographic.fromDegrees(-101.0, 34.0), - Cartographic.fromDegrees(-101.0, 36.0), - Cartographic.fromDegrees(-103.0, 36.0) - ]) - }] + Cartographic.fromDegrees(-103.0, 34.0), + Cartographic.fromDegrees(-101.0, 34.0), + Cartographic.fromDegrees(-101.0, 36.0), + Cartographic.fromDegrees(-103.0, 36.0) + ]) }] }] - }, - pickData : 'polygon3' - }); + }] + }, + pickData : 'polygon3', + stRotation : 0.523598776 + }); + + var a = Appearance.ELLIPSOID_SURFACE; + a.material = Material.fromType(scene.getContext(), 'Stripe'); widget.scene.getPrimitives().add(new Primitive({ geometries : polygonGeometry, - appearance : Appearance.CLOSED_TRANSLUCENT + appearance : Appearance.ELLIPSOID_SURFACE })); var handler = new ScreenSpaceEventHandler(scene.getCanvas()); diff --git a/Source/Core/ExtentGeometry.js b/Source/Core/ExtentGeometry.js index 39fabb50008d..e0e0992a0e2c 100644 --- a/Source/Core/ExtentGeometry.js +++ b/Source/Core/ExtentGeometry.js @@ -62,8 +62,9 @@ define([ * Creates geometry for a cartographic extent on an ellipsoid centered at the origin. * * @param {Extent} options.extent A cartographic extent with north, south, east and west properties in radians. + * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed. * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid on which the extent lies. - * @param {Number} [options.granularity=0.1] The distance, in radians, between each latitude and longitude. Determines the number of positions in the buffer. + * @param {Number} [options.granularity=CesiumMath.toRadians(1.0)] The distance, in radians, between each latitude and longitude. Determines the number of positions in the buffer. * @param {Number} [options.surfaceHeight=0.0] The height from the surface of the ellipsoid. * @param {Number} [options.rotation=0.0] The rotation of the extent in radians. A positive rotation is counter-clockwise. * @param {Matrix4} [options.modelMatrix] The model matrix for this geometry. @@ -90,7 +91,6 @@ define([ * CesiumMath.toRadians(-74.0), * CesiumMath.toRadians(42.0) * ), - * granularity : 0.01, * surfaceHeight : 10000.0 * }); */ @@ -104,7 +104,7 @@ define([ extent.validate(); - var granularity = defaultValue(options.granularity, 0.1); + var granularity = defaultValue(granularity, CesiumMath.toRadians(1.0)); var width = Math.ceil((extent.east - extent.west) / granularity) + 1; var height = Math.ceil((extent.north - extent.south) / granularity) + 1; var granularityX = (extent.east - extent.west) / (width - 1); diff --git a/Source/Core/PolygonGeometry.js b/Source/Core/PolygonGeometry.js index 0e2d955e18a5..54aee7913c1d 100644 --- a/Source/Core/PolygonGeometry.js +++ b/Source/Core/PolygonGeometry.js @@ -1,13 +1,19 @@ /*global define*/ define([ './DeveloperError', + './Cartesian2', + './Cartesian3', './Cartesian4', + './Quaternion', './Ellipsoid', + './Matrix3', './Matrix4', + './Math', './ComponentDatatype', './PrimitiveType', './defaultValue', './BoundingSphere', + './BoundingRectangle', './GeometryAttribute', './GeometryIndices', './PolygonPipeline', @@ -15,16 +21,23 @@ define([ './WindingOrder', './GeometryFilters', './Queue', - './Intersect' + './Intersect', + './VertexFormat' ], function( DeveloperError, + Cartesian2, + Cartesian3, Cartesian4, + Quaternion, Ellipsoid, + Matrix3, Matrix4, + CesiumMath, ComponentDatatype, PrimitiveType, defaultValue, BoundingSphere, + BoundingRectangle, GeometryAttribute, GeometryIndices, PolygonPipeline, @@ -32,10 +45,90 @@ define([ WindingOrder, GeometryFilters, Queue, - Intersect) { + Intersect, + VertexFormat) { "use strict"; - function createMeshFromPositions(ellipsoid, positions, boundingSphere, outerPositions) { + var computeBoundingRectangleCartesian2 = new Cartesian2(); + var computeBoundingRectangleCartesian3 = new Cartesian3(); + var computeBoundingRectangleQuaternion = new Quaternion(); + var computeBoundingRectangleMatrix3 = new Matrix3(); + + function computeBoundingRectangle(tangentPlane, positions, angle, result) { + var rotation = Quaternion.fromAxisAngle(tangentPlane._plane.normal, angle, computeBoundingRectangleQuaternion); + var textureMatrix = Matrix3.fromQuaternion(rotation,computeBoundingRectangleMatrix3); + + var minX = Number.POSITIVE_INFINITY; + var maxX = Number.NEGATIVE_INFINITY; + var minY = Number.POSITIVE_INFINITY; + var maxY = Number.NEGATIVE_INFINITY; + + var length = positions.length; + for ( var i = 0; i < length; ++i) { + var p = Cartesian3.clone(positions[i], computeBoundingRectangleCartesian3); + Matrix3.multiplyByVector(textureMatrix, p, p); + var st = tangentPlane.projectPointOntoPlane(p, computeBoundingRectangleCartesian2); + + if (typeof st !== 'undefined') { + minX = Math.min(minX, st.x); + maxX = Math.max(maxX, st.x); + + minY = Math.min(minY, st.y); + maxY = Math.max(maxY, st.y); + } + } + + if (typeof result === 'undefined') { + result = new BoundingRectangle(); + } + + result.x = minX; + result.y = minY; + result.width = maxX - minX; + result.height = maxY - minY; + return result; + } + + var appendTextureCoordinatesCartesian2 = new Cartesian2(); + var appendTextureCoordinatesCartesian3 = new Cartesian3(); + var appendTextureCoordinatesQuaternion = new Quaternion(); + var appendTextureCoordinatesMatrix3 = new Matrix3(); + + function appendTextureCoordinates(mesh, tangentPlane, boundingRectangle, angle) { + var origin = new Cartesian2(boundingRectangle.x, boundingRectangle.y); + + var positions = mesh.attributes.position.values; + var length = positions.length; + + var textureCoordinates = new Float32Array(2 * (length / 3)); + var j = 0; + + var rotation = Quaternion.fromAxisAngle(tangentPlane._plane.normal, angle, appendTextureCoordinatesQuaternion); + var textureMatrix = Matrix3.fromQuaternion(rotation, appendTextureCoordinatesMatrix3); + + for ( var i = 0; i < length; i += 3) { + var p = appendTextureCoordinatesCartesian3; + p.x = positions[i]; + p.y = positions[i + 1]; + p.z = positions[i + 2]; + Matrix3.multiplyByVector(textureMatrix, p, p); + var st = tangentPlane.projectPointOntoPlane(p, appendTextureCoordinatesCartesian2); + st.subtract(origin, st); + + textureCoordinates[j++] = st.x / boundingRectangle.width; + textureCoordinates[j++] = st.y / boundingRectangle.height; + } + + mesh.attributes.st = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 2, + values : textureCoordinates + }); + + return mesh; + } + + function createMeshFromPositions(ellipsoid, positions, boundingSphere, granularity) { var cleanedPositions = PolygonPipeline.cleanUp(positions); if (cleanedPositions.length < 3) { // Duplicate positions result in not enough positions to form a polygon. @@ -56,11 +149,11 @@ define([ if ((minX < 0) && (BoundingSphere.intersect(boundingSphere, Cartesian4.UNIT_Y) === Intersect.INTERSECTING)) { indices = PolygonPipeline.wrapLongitude(cleanedPositions, indices); } - var mesh = PolygonPipeline.computeSubdivision(cleanedPositions, indices); - - return mesh; + return PolygonPipeline.computeSubdivision(cleanedPositions, indices, granularity); } + var scratchBoundingRectangle = new BoundingRectangle(); + /** * Creates a PolygonGeometry. The polygon itself is either defined by an array of Cartesian points, * or a polygon hierarchy. @@ -68,10 +161,13 @@ define([ * @alias PolygonGeometry * @constructor * - * @param {Array} [options.positions] an array of positions that defined the corner points of the polygon - * @param {Object} [options.polygonHierarchy] a polygon hierarchy that can include holes - * @param {Number} [options.height=0.0] the height of the polygon, - * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] the ellipsoid to be used as a reference + * @param {Array} [options.positions] An array of positions that defined the corner points of the polygon. + * @param {Object} [options.polygonHierarchy] A polygon hierarchy that can include holes. + * @param {Number} [options.height=0.0] The height of the polygon. + * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed. + * @param {Number} [options.stRotation=0.0] The rotation of the texture coordiantes, in radians. A positive rotation is counter-clockwise. + * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid to be used as a reference. + * @param {Number} [options.granularity=CesiumMath.toRadians(1.0)] The distance, in radians, between each latitude and longitude. Determines the number of positions in the buffer. * @param {Matrix4} [options.modelMatrix] The model matrix for this geometry. * @param {Color} [options.color] The color of the geometry when a per-geometry color appearance is used. * @param {DOC_TBA} [options.pickData] DOC_TBA @@ -134,7 +230,10 @@ define([ var PolygonGeometry = function(options) { options = defaultValue(options, defaultValue.EMPTY_OBJECT); + var vertexFormat = defaultValue(options.vertexFormat, VertexFormat.DEFAULT); var ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84); + var granularity = defaultValue(options.granularity, CesiumMath.toRadians(1.0)); + var stRotation = defaultValue(options.stRotation, 0.0); var meshes = []; var mesh; @@ -143,12 +242,15 @@ define([ var positions; var polygonHierarchy; + var outerPositions; + if (typeof options.positions !== 'undefined') { // create from positions positions = options.positions; + outerPositions = options.positions; boundingSphere = BoundingSphere.fromPoints(positions); - mesh = createMeshFromPositions(ellipsoid, positions, boundingSphere); + mesh = createMeshFromPositions(ellipsoid, positions, boundingSphere, granularity); if (typeof mesh !== 'undefined') { meshes.push(mesh); } @@ -181,7 +283,7 @@ define([ holes.push(hole.positions); var numGrandchildren = 0; - if (hole.holes) { + if (typeof hole.holes !== 'undefined') { numGrandchildren = hole.holes.length; } @@ -196,14 +298,14 @@ define([ polygonHierarchy = polygons; - var outerPositions = polygonHierarchy[0]; + outerPositions = polygonHierarchy[0]; // The bounding volume is just around the boundary points, so there could be cases for // contrived polygons on contrived ellipsoids - very oblate ones - where the bounding // volume doesn't cover the polygon. boundingSphere = BoundingSphere.fromPoints(outerPositions); for (i = 0; i < polygonHierarchy.length; i++) { - mesh = createMeshFromPositions(ellipsoid, polygonHierarchy[i], boundingSphere); + mesh = createMeshFromPositions(ellipsoid, polygonHierarchy[i], boundingSphere, granularity); if (typeof mesh !== 'undefined') { meshes.push(mesh); } @@ -224,6 +326,21 @@ define([ values : mesh.attributes.position.values }); + if (vertexFormat.st) { + // PERFORMANCE_IDEA: Compute before subdivision, then just interpolate during subdivision. + // PERFORMANCE_IDEA: Compute with createMeshFromPositions() for fast path when there's no holes. + var cleanedPositions = PolygonPipeline.cleanUp(outerPositions); + var tangentPlane = EllipsoidTangentPlane.fromPoints(cleanedPositions, ellipsoid); + var boundingRectangle = computeBoundingRectangle(tangentPlane, outerPositions, stRotation, scratchBoundingRectangle); + mesh = appendTextureCoordinates(mesh, tangentPlane, boundingRectangle, stRotation); + + attributes.st = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 2, + values : mesh.attributes.st.values + }); + } + indexLists.push( new GeometryIndices({ primitiveType : PrimitiveType.TRIANGLES, diff --git a/Source/Core/VertexFormat.js b/Source/Core/VertexFormat.js index a31aca3f8f4a..eee443445237 100644 --- a/Source/Core/VertexFormat.js +++ b/Source/Core/VertexFormat.js @@ -72,6 +72,16 @@ define([ normal : true })); + /** + * DOC_TBA + * + * For use with ellipsoid-surface appearance. + */ + VertexFormat.POSITION_AND_ST = freezeObject(new VertexFormat({ + position : true, + st : true + })); + /** * DOC_TBA */ diff --git a/Source/Scene/Appearance.js b/Source/Scene/Appearance.js index a93eccee0856..16e9a940917b 100644 --- a/Source/Scene/Appearance.js +++ b/Source/Scene/Appearance.js @@ -8,7 +8,9 @@ define([ '../Shaders/Appearances/DefaultAppearanceVS', '../Shaders/Appearances/DefaultAppearanceFS', '../Shaders/Appearances/PerGeometryColorAppearanceVS', - '../Shaders/Appearances/PerGeometryColorAppearanceFS' + '../Shaders/Appearances/PerGeometryColorAppearanceFS', + '../Shaders/Appearances/EllipsoidSurfaceAppearanceVS', + '../Shaders/Appearances/EllipsoidSurfaceAppearanceFS' ], function( defaultValue, freezeObject, @@ -18,7 +20,9 @@ define([ DefaultAppearanceVS, DefaultAppearanceFS, PerGeometryColorAppearanceVS, - PerGeometryColorDefaultAppearanceFS) { + PerGeometryColorDefaultAppearanceFS, + EllipsoidSurfaceAppearanceVS, + EllipsoidSurfaceAppearanceFS) { "use strict"; /** @@ -94,5 +98,24 @@ define([ } })); + /** + * DOC_TBA + */ + Appearance.ELLIPSOID_SURFACE = /*freezeObject*/(new Appearance({ + vertexShaderSource : EllipsoidSurfaceAppearanceVS, + fragmentShaderSource : EllipsoidSurfaceAppearanceFS, + renderState : { + cull : { + enabled : true, + face : CullFace.BACK + }, + depthTest : { + enabled : true + }, + depthMask : false, + blending : BlendingState.ALPHA_BLEND + } + })); + return Appearance; }); \ No newline at end of file diff --git a/Source/Scene/Polygon.js b/Source/Scene/Polygon.js index a0734dced0ae..be094e6d1569 100644 --- a/Source/Scene/Polygon.js +++ b/Source/Scene/Polygon.js @@ -464,6 +464,7 @@ define([ var minY = Number.POSITIVE_INFINITY; var maxY = Number.NEGATIVE_INFINITY; + var length = positions.length; for ( var i = 0; i < length; ++i) { var p = Cartesian3.clone(positions[i], computeBoundingRectangleCartesian3); diff --git a/Source/Shaders/Appearances/EllipsoidSurfaceAppearanceFS.glsl b/Source/Shaders/Appearances/EllipsoidSurfaceAppearanceFS.glsl new file mode 100644 index 000000000000..453eade65cb4 --- /dev/null +++ b/Source/Shaders/Appearances/EllipsoidSurfaceAppearanceFS.glsl @@ -0,0 +1,25 @@ +varying vec3 v_positionMC; +varying vec3 v_positionEC; +varying vec2 v_st; + +void main() +{ + czm_materialInput materialInput; + + materialInput.s = v_st.s; + materialInput.st = v_st; + materialInput.str = vec3(v_st, 0.0); + + // Convert tangent space material normal to eye space + materialInput.normalEC = normalize(czm_normal3D * czm_geodeticSurfaceNormal(v_positionMC, vec3(0.0), vec3(1.0))); + materialInput.tangentToEyeMatrix = czm_eastNorthUpToEyeCoordinates(v_positionMC, materialInput.normalEC); + + // Convert view vector to world space + vec3 positionToEyeEC = -v_positionEC; + materialInput.positionToEyeEC = positionToEyeEC; + + czm_material material = czm_getMaterial(materialInput); + + gl_FragColor = czm_phong(normalize(positionToEyeEC), material); +// gl_FragColor = vec4(material.diffuse + material.emission, material.alpha); +} diff --git a/Source/Shaders/Appearances/EllipsoidSurfaceAppearanceVS.glsl b/Source/Shaders/Appearances/EllipsoidSurfaceAppearanceVS.glsl new file mode 100644 index 000000000000..b33700b32729 --- /dev/null +++ b/Source/Shaders/Appearances/EllipsoidSurfaceAppearanceVS.glsl @@ -0,0 +1,21 @@ +attribute vec3 positionHigh; +attribute vec3 positionLow; +attribute vec2 st; +attribute vec4 pickColor; + +varying vec3 v_positionMC; +varying vec3 v_positionEC; +varying vec2 v_st; +varying vec4 czm_pickColor; + +void main() +{ + vec4 p = czm_translateRelativeToEye(positionHigh, positionLow); + + v_positionMC = positionHigh + positionLow; // position in model coordinates + v_positionEC = (czm_modelViewRelativeToEye * p).xyz; // position in eye coordinates + v_st = st; + czm_pickColor = pickColor; + + gl_Position = czm_modelViewProjectionRelativeToEye * p; +} From fc748412993b6b9e3e6abcfabc870dc4119d9e9c Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Mon, 3 Jun 2013 15:36:57 -0400 Subject: [PATCH 128/306] Fixed tests --- Source/Core/ExtentGeometry.js | 2 +- Source/Core/PolygonGeometry.js | 5 +---- Source/Scene/Polygon.js | 1 - 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/Source/Core/ExtentGeometry.js b/Source/Core/ExtentGeometry.js index e0e0992a0e2c..444439af85ad 100644 --- a/Source/Core/ExtentGeometry.js +++ b/Source/Core/ExtentGeometry.js @@ -104,7 +104,7 @@ define([ extent.validate(); - var granularity = defaultValue(granularity, CesiumMath.toRadians(1.0)); + var granularity = defaultValue(options.granularity, CesiumMath.toRadians(1.0)); var width = Math.ceil((extent.east - extent.west) / granularity) + 1; var height = Math.ceil((extent.north - extent.south) / granularity) + 1; var granularityX = (extent.east - extent.west) / (width - 1); diff --git a/Source/Core/PolygonGeometry.js b/Source/Core/PolygonGeometry.js index 54aee7913c1d..30ba69cb712c 100644 --- a/Source/Core/PolygonGeometry.js +++ b/Source/Core/PolygonGeometry.js @@ -107,10 +107,7 @@ define([ var textureMatrix = Matrix3.fromQuaternion(rotation, appendTextureCoordinatesMatrix3); for ( var i = 0; i < length; i += 3) { - var p = appendTextureCoordinatesCartesian3; - p.x = positions[i]; - p.y = positions[i + 1]; - p.z = positions[i + 2]; + var p = Cartesian3.fromArray(positions, i, appendTextureCoordinatesCartesian3); Matrix3.multiplyByVector(textureMatrix, p, p); var st = tangentPlane.projectPointOntoPlane(p, appendTextureCoordinatesCartesian2); st.subtract(origin, st); diff --git a/Source/Scene/Polygon.js b/Source/Scene/Polygon.js index be094e6d1569..a0734dced0ae 100644 --- a/Source/Scene/Polygon.js +++ b/Source/Scene/Polygon.js @@ -464,7 +464,6 @@ define([ var minY = Number.POSITIVE_INFINITY; var maxY = Number.NEGATIVE_INFINITY; - var length = positions.length; for ( var i = 0; i < length; ++i) { var p = Cartesian3.clone(positions[i], computeBoundingRectangleCartesian3); From 7aca3224a74c7b31b4776836e42f6a64a2a6fb72 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 3 Jun 2013 15:37:07 -0400 Subject: [PATCH 129/306] Fixes after merge. --- Source/Core/PolygonGeometry.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Source/Core/PolygonGeometry.js b/Source/Core/PolygonGeometry.js index 4b291fbee9ef..2ef836db0d40 100644 --- a/Source/Core/PolygonGeometry.js +++ b/Source/Core/PolygonGeometry.js @@ -13,6 +13,7 @@ define([ './GeometryAttribute', './GeometryFilters', './Intersect', + './Math', './Matrix3', './Matrix4', './PolygonPipeline', @@ -34,6 +35,7 @@ define([ GeometryAttribute, GeometryFilters, Intersect, + CesiumMath, Matrix3, Matrix4, PolygonPipeline, @@ -122,6 +124,8 @@ define([ return mesh; } + var createMeshFromPositionsPositions = []; + function createMeshFromPositions(ellipsoid, positions, boundingSphere, granularity) { var cleanedPositions = PolygonPipeline.cleanUp(positions); if (cleanedPositions.length < 3) { @@ -148,6 +152,7 @@ define([ return PolygonPipeline.computeSubdivision(cleanedPositions, indices, granularity); } + var scratchBoundingRectangle = new BoundingRectangle(); /** * Computes vertices and indices for a polygon on the ellipsoid. The polygon is either defined @@ -225,6 +230,10 @@ define([ var ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84); var granularity = defaultValue(options.granularity, CesiumMath.toRadians(1.0)); var stRotation = defaultValue(options.stRotation, 0.0); + var height = defaultValue(options.height, 0.0); + + var positions = options.positions; + var polygonHierarchy = options.polygonHierarchy; var meshes = []; var mesh; @@ -235,8 +244,7 @@ define([ if (typeof options.positions !== 'undefined') { // create from positions - positions = options.positions; - outerPositions = options.positions; + outerPositions = positions; boundingSphere = BoundingSphere.fromPoints(positions); mesh = createMeshFromPositions(ellipsoid, positions, boundingSphere, granularity); From 351ab547794c171ea381ce5acce3746dc09066b0 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 3 Jun 2013 15:47:04 -0400 Subject: [PATCH 130/306] More clean up after merge. --- Source/Core/PolygonGeometry.js | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/Source/Core/PolygonGeometry.js b/Source/Core/PolygonGeometry.js index a43856da9691..318cebbdb507 100644 --- a/Source/Core/PolygonGeometry.js +++ b/Source/Core/PolygonGeometry.js @@ -52,7 +52,7 @@ define([ function computeBoundingRectangle(tangentPlane, positions, angle, result) { var rotation = Quaternion.fromAxisAngle(tangentPlane._plane.normal, angle, computeBoundingRectangleQuaternion); - var textureMatrix = Matrix3.fromQuaternion(rotation,computeBoundingRectangleMatrix3); + var textureMatrix = Matrix3.fromQuaternion(rotation, computeBoundingRectangleMatrix3); var minX = Number.POSITIVE_INFINITY; var maxX = Number.NEGATIVE_INFINITY; @@ -85,13 +85,16 @@ define([ return result; } + var appendTextureCoordinatesOrigin = new Cartesian2(); var appendTextureCoordinatesCartesian2 = new Cartesian2(); var appendTextureCoordinatesCartesian3 = new Cartesian3(); var appendTextureCoordinatesQuaternion = new Quaternion(); var appendTextureCoordinatesMatrix3 = new Matrix3(); function appendTextureCoordinates(mesh, tangentPlane, boundingRectangle, angle) { - var origin = new Cartesian2(boundingRectangle.x, boundingRectangle.y); + var origin = appendTextureCoordinatesOrigin; + origin.x = boundingRectangle.x; + origin.y = boundingRectangle.y; var positions = mesh.attributes.position.values; var length = positions.length; @@ -239,7 +242,7 @@ define([ var outerPositions; - if (typeof options.positions !== 'undefined') { + if (typeof positions !== 'undefined') { // create from positions outerPositions = positions; @@ -279,7 +282,7 @@ define([ numGrandchildren = hole.holes.length; } - for ( var j = 0; j < numGrandchildren; j++) { + for (var j = 0; j < numGrandchildren; j++) { queue.enqueue(hole.holes[j]); } } @@ -315,10 +318,6 @@ define([ attributes.position = mesh.attributes.position; } - if (vertexFormat.st) { - attributes.st = mesh.attributes.st; - } - if (vertexFormat.st) { // PERFORMANCE_IDEA: Compute before subdivision, then just interpolate during subdivision. // PERFORMANCE_IDEA: Compute with createMeshFromPositions() for fast path when there's no holes. @@ -326,12 +325,7 @@ define([ var tangentPlane = EllipsoidTangentPlane.fromPoints(cleanedPositions, ellipsoid); var boundingRectangle = computeBoundingRectangle(tangentPlane, outerPositions, stRotation, scratchBoundingRectangle); mesh = appendTextureCoordinates(mesh, tangentPlane, boundingRectangle, stRotation); - - attributes.st = new GeometryAttribute({ - componentDatatype : ComponentDatatype.FLOAT, - componentsPerAttribute : 2, - values : mesh.attributes.st.values - }); + attributes.st = mesh.attributes.st; } /** From 6fd4fec7f2fd4e498409c495baee86ace25e5f45 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Mon, 3 Jun 2013 16:33:06 -0400 Subject: [PATCH 131/306] Created types for apparances --- Apps/CesiumViewer/CesiumViewer.js | 16 ++-- Apps/Sandcastle/gallery/Wall.html | 16 +--- Source/Scene/Appearance.js | 73 +------------------ Source/Scene/ClosedTranslucentAppearance.js | 63 ++++++++++++++++ Source/Scene/EllipsoidSurfaceAppearance.js | 63 ++++++++++++++++ ...eometryColorClosedTranslucentAppearance.js | 62 ++++++++++++++++ Source/Scene/Primitive.js | 6 +- Source/Scene/TranslucentAppearance.js | 57 +++++++++++++++ 8 files changed, 262 insertions(+), 94 deletions(-) create mode 100644 Source/Scene/ClosedTranslucentAppearance.js create mode 100644 Source/Scene/EllipsoidSurfaceAppearance.js create mode 100644 Source/Scene/PerGeometryColorClosedTranslucentAppearance.js create mode 100644 Source/Scene/TranslucentAppearance.js diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index b8485ad4322d..1cd667b815a0 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -24,6 +24,9 @@ define([ 'Core/ScreenSpaceEventType', 'Scene/Primitive', 'Scene/Appearance', + 'Scene/ClosedTranslucentAppearance', + 'Scene/PerGeometryColorClosedTranslucentAppearance', + 'Scene/EllipsoidSurfaceAppearance', 'Scene/Material', 'Widgets/Dojo/checkForChromeFrame', 'Widgets/Dojo/CesiumViewerWidget' @@ -52,6 +55,9 @@ define([ ScreenSpaceEventType, Primitive, Appearance, + ClosedTranslucentAppearance, + PerGeometryColorClosedTranslucentAppearance, + EllipsoidSurfaceAppearance, Material, checkForChromeFrame, CesiumViewerWidget) { @@ -124,7 +130,7 @@ define([ var primitive = new Primitive({ geometries : [mesh, mesh2, mesh3, mesh4], - appearance : Appearance.PER_GEOMETRY_COLOR_CLOSED_TRANSLUCENT + appearance : new PerGeometryColorClosedTranslucentAppearance() }); scene.getPrimitives().add(primitive); @@ -191,7 +197,6 @@ define([ Cartographic.fromDegrees(-68.0, 40.0) ]), */ - polygonHierarchy : { positions : ellipsoid.cartographicArrayToCartesianArray([ Cartographic.fromDegrees(-109.0, 30.0), @@ -228,12 +233,11 @@ define([ stRotation : 0.523598776 }); - var a = Appearance.ELLIPSOID_SURFACE; - a.material = Material.fromType(scene.getContext(), 'Stripe'); - widget.scene.getPrimitives().add(new Primitive({ geometries : polygonGeometry, - appearance : Appearance.ELLIPSOID_SURFACE + appearance : new EllipsoidSurfaceAppearance({ + material : Material.fromType(scene.getContext(), 'Stripe') + }) })); var handler = new ScreenSpaceEventHandler(scene.getCanvas()); diff --git a/Apps/Sandcastle/gallery/Wall.html b/Apps/Sandcastle/gallery/Wall.html index a10a97e7ff37..4ea17b7b2aff 100644 --- a/Apps/Sandcastle/gallery/Wall.html +++ b/Apps/Sandcastle/gallery/Wall.html @@ -55,21 +55,7 @@ var ellipsoid = widget.centralBody.getEllipsoid(); var primitives = scene.getPrimitives(); - var material = Cesium.Material.fromType(undefined, Cesium.Material.ColorType); - material.uniforms.color = new Cesium.Color(1.0, 0.0, 0, 0.3); - var appearance = new Cesium.Appearance({ - renderState : { - cull : { - enabled : false - }, - depthTest : { - enabled : true - }, - depthMask : false, - blending : Cesium.BlendingState.ALPHA_BLEND - }, - material : material - }); + var appearance = new Cesium.TranslucentAppearance(); var positions = [ Cesium.Cartographic.fromDegrees(19.0, 47.0, 10000.0), diff --git a/Source/Scene/Appearance.js b/Source/Scene/Appearance.js index 16e9a940917b..58a9aef117e5 100644 --- a/Source/Scene/Appearance.js +++ b/Source/Scene/Appearance.js @@ -1,28 +1,14 @@ /*global define*/ define([ '../Core/defaultValue', - '../Core/freezeObject', - '../Renderer/CullFace', - '../Renderer/BlendingState', './Material', '../Shaders/Appearances/DefaultAppearanceVS', - '../Shaders/Appearances/DefaultAppearanceFS', - '../Shaders/Appearances/PerGeometryColorAppearanceVS', - '../Shaders/Appearances/PerGeometryColorAppearanceFS', - '../Shaders/Appearances/EllipsoidSurfaceAppearanceVS', - '../Shaders/Appearances/EllipsoidSurfaceAppearanceFS' + '../Shaders/Appearances/DefaultAppearanceFS' ], function( defaultValue, - freezeObject, - CullFace, - BlendingState, Material, DefaultAppearanceVS, - DefaultAppearanceFS, - PerGeometryColorAppearanceVS, - PerGeometryColorDefaultAppearanceFS, - EllipsoidSurfaceAppearanceVS, - EllipsoidSurfaceAppearanceFS) { + DefaultAppearanceFS) { "use strict"; /** @@ -62,60 +48,5 @@ define([ this.fragmentShaderSource; }; - /** - * DOC_TBA - */ - Appearance.CLOSED_TRANSLUCENT = freezeObject(new Appearance({ - renderState : { - cull : { - enabled : true, - face : CullFace.BACK - }, - depthTest : { - enabled : true - }, - depthMask : false, - blending : BlendingState.ALPHA_BLEND - } - })); - - /** - * DOC_TBA - */ - Appearance.PER_GEOMETRY_COLOR_CLOSED_TRANSLUCENT = freezeObject(new Appearance({ - vertexShaderSource : PerGeometryColorAppearanceVS, - fragmentShaderSource : PerGeometryColorDefaultAppearanceFS, - renderState : { - cull : { - enabled : true, - face : CullFace.BACK - }, - depthTest : { - enabled : true - }, - depthMask : false, - blending : BlendingState.ALPHA_BLEND - } - })); - - /** - * DOC_TBA - */ - Appearance.ELLIPSOID_SURFACE = /*freezeObject*/(new Appearance({ - vertexShaderSource : EllipsoidSurfaceAppearanceVS, - fragmentShaderSource : EllipsoidSurfaceAppearanceFS, - renderState : { - cull : { - enabled : true, - face : CullFace.BACK - }, - depthTest : { - enabled : true - }, - depthMask : false, - blending : BlendingState.ALPHA_BLEND - } - })); - return Appearance; }); \ No newline at end of file diff --git a/Source/Scene/ClosedTranslucentAppearance.js b/Source/Scene/ClosedTranslucentAppearance.js new file mode 100644 index 000000000000..f583132a1240 --- /dev/null +++ b/Source/Scene/ClosedTranslucentAppearance.js @@ -0,0 +1,63 @@ +/*global define*/ +define([ + '../Core/defaultValue', + '../Renderer/CullFace', + '../Renderer/BlendingState', + './Material', + './Appearance', + '../Shaders/Appearances/DefaultAppearanceVS', + '../Shaders/Appearances/DefaultAppearanceFS' + ], function( + defaultValue, + CullFace, + BlendingState, + Material, + Appearance, + DefaultAppearanceVS, + DefaultAppearanceFS) { + "use strict"; + + /** + * DOC_TBA + */ + var ClosedTranslucentAppearance = function(options) { + options = defaultValue(options, defaultValue.EMPTY_OBJECT); + + /** + * DOC_TBA + */ + this.material = (typeof options.material !== 'undefined') ? options.material : Material.fromType(undefined, Material.ColorType); + + /** + * DOC_TBA + */ + this.vertexShaderSource = defaultValue(options.vertexShaderSource, DefaultAppearanceVS); + + /** + * DOC_TBA + */ + this.fragmentShaderSource = defaultValue(options.fragmentShaderSource, DefaultAppearanceFS); + + /** + * DOC_TBA + */ + this.renderState = defaultValue(options.renderState, { + cull : { + enabled : true, + face : CullFace.BACK + }, + depthTest : { + enabled : true + }, + depthMask : false, + blending : BlendingState.ALPHA_BLEND + }); + }; + + /** + * DOC_TBA + */ + ClosedTranslucentAppearance.prototype.getFragmentShaderSource = Appearance.prototype.getFragmentShaderSource; + + return ClosedTranslucentAppearance; +}); \ No newline at end of file diff --git a/Source/Scene/EllipsoidSurfaceAppearance.js b/Source/Scene/EllipsoidSurfaceAppearance.js new file mode 100644 index 000000000000..e2da7431b5d0 --- /dev/null +++ b/Source/Scene/EllipsoidSurfaceAppearance.js @@ -0,0 +1,63 @@ +/*global define*/ +define([ + '../Core/defaultValue', + '../Renderer/CullFace', + '../Renderer/BlendingState', + './Material', + './Appearance', + '../Shaders/Appearances/EllipsoidSurfaceAppearanceVS', + '../Shaders/Appearances/EllipsoidSurfaceAppearanceFS' + ], function( + defaultValue, + CullFace, + BlendingState, + Material, + Appearance, + EllipsoidSurfaceAppearanceVS, + EllipsoidSurfaceAppearanceFS) { + "use strict"; + + /** + * DOC_TBA + */ + var EllipsoidSurfaceAppearance = function(options) { + options = defaultValue(options, defaultValue.EMPTY_OBJECT); + + /** + * DOC_TBA + */ + this.material = (typeof options.material !== 'undefined') ? options.material : Material.fromType(undefined, Material.ColorType); + + /** + * DOC_TBA + */ + this.vertexShaderSource = defaultValue(options.vertexShaderSource, EllipsoidSurfaceAppearanceVS); + + /** + * DOC_TBA + */ + this.fragmentShaderSource = defaultValue(options.fragmentShaderSource, EllipsoidSurfaceAppearanceFS); + + /** + * DOC_TBA + */ + this.renderState = defaultValue(options.renderState, { + cull : { + enabled : true, + face : CullFace.BACK + }, + depthTest : { + enabled : true + }, + depthMask : false, + blending : BlendingState.ALPHA_BLEND + }); + }; + + /** + * DOC_TBA + */ + EllipsoidSurfaceAppearance.prototype.getFragmentShaderSource = Appearance.prototype.getFragmentShaderSource; + + return EllipsoidSurfaceAppearance; +}); \ No newline at end of file diff --git a/Source/Scene/PerGeometryColorClosedTranslucentAppearance.js b/Source/Scene/PerGeometryColorClosedTranslucentAppearance.js new file mode 100644 index 000000000000..08f5d7e6c2a1 --- /dev/null +++ b/Source/Scene/PerGeometryColorClosedTranslucentAppearance.js @@ -0,0 +1,62 @@ +/*global define*/ +define([ + '../Core/defaultValue', + '../Renderer/CullFace', + '../Renderer/BlendingState', + '../Shaders/Appearances/PerGeometryColorAppearanceVS', + '../Shaders/Appearances/PerGeometryColorAppearanceFS' + ], function( + defaultValue, + CullFace, + BlendingState, + PerGeometryColorAppearanceVS, + PerGeometryColorDefaultAppearanceFS) { + "use strict"; + + /** + * DOC_TBA + */ + var PerGeometryColorClosedTranslucentAppearance = function(options) { + options = defaultValue(options, defaultValue.EMPTY_OBJECT); + + /** + * DOC_TBA + */ + this.material = undefined; + + /** + * DOC_TBA + */ + this.vertexShaderSource = defaultValue(options.vertexShaderSource, PerGeometryColorAppearanceVS); + + /** + * DOC_TBA + */ + this.fragmentShaderSource = defaultValue(options.fragmentShaderSource, PerGeometryColorDefaultAppearanceFS); + + /** + * DOC_TBA + */ + this.renderState = defaultValue(options.renderState, { + cull : { + enabled : true, + face : CullFace.BACK + }, + depthTest : { + enabled : true + }, + depthMask : false, + blending : BlendingState.ALPHA_BLEND + }); + }; + + /** + * DOC_TBA + */ + PerGeometryColorClosedTranslucentAppearance.prototype.getFragmentShaderSource = function() { + // Unlike other appearances, this does not have a material + return this.fragmentShaderSource; + }; + + return PerGeometryColorClosedTranslucentAppearance; +}); \ No newline at end of file diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index 2554e32405c5..f985c72a043a 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -384,6 +384,8 @@ define([ pickRS = context.createRenderState(appearanceRS); } + var uniforms = (typeof appearance.material !== 'undefined') ? appearance.material._uniforms : undefined; + for (i = 0; i < length; ++i) { var geometry = finalGeometries[i]; @@ -393,7 +395,7 @@ define([ command.vertexArray = this._va[i]; command.renderState = rs; command.shaderProgram = this._sp; - command.uniformMap = appearance.material._uniforms; + command.uniformMap = uniforms; command.boundingVolume = geometry.boundingSphere; colorCommands.push(command); @@ -402,7 +404,7 @@ define([ pickCommand.vertexArray = this._va[i]; pickCommand.renderState = pickRS; pickCommand.shaderProgram = this._pickSP; - pickCommand.uniformMap = appearance.material._uniforms; + pickCommand.uniformMap = uniforms; pickCommand.boundingVolume = geometry.boundingSphere; pickCommands.push(pickCommand); } diff --git a/Source/Scene/TranslucentAppearance.js b/Source/Scene/TranslucentAppearance.js new file mode 100644 index 000000000000..fd3eb3069e8c --- /dev/null +++ b/Source/Scene/TranslucentAppearance.js @@ -0,0 +1,57 @@ +/*global define*/ +define([ + '../Core/defaultValue', + '../Renderer/BlendingState', + './Material', + './Appearance', + '../Shaders/Appearances/DefaultAppearanceVS', + '../Shaders/Appearances/DefaultAppearanceFS' + ], function( + defaultValue, + BlendingState, + Material, + Appearance, + DefaultAppearanceVS, + DefaultAppearanceFS) { + "use strict"; + + /** + * DOC_TBA + */ + var TranslucentAppearance = function(options) { + options = defaultValue(options, defaultValue.EMPTY_OBJECT); + + /** + * DOC_TBA + */ + this.material = (typeof options.material !== 'undefined') ? options.material : Material.fromType(undefined, Material.ColorType); + + /** + * DOC_TBA + */ + this.vertexShaderSource = defaultValue(options.vertexShaderSource, DefaultAppearanceVS); + + /** + * DOC_TBA + */ + this.fragmentShaderSource = defaultValue(options.fragmentShaderSource, DefaultAppearanceFS); + + /** + * DOC_TBA + */ + this.renderState = defaultValue(options.renderState, { + depthTest : { + enabled : true + }, + depthMask : false, + blending : BlendingState.ALPHA_BLEND + }); + }; + + /** + * DOC_TBA + */ + TranslucentAppearance.prototype.getFragmentShaderSource = Appearance.prototype.getFragmentShaderSource; + + return TranslucentAppearance; +}); \ No newline at end of file From 34cdefc87d106893e1395af1c181cbb67780f474 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 3 Jun 2013 16:50:00 -0400 Subject: [PATCH 132/306] Add normal, tangent, and binormal attributes to polygon geometry. --- Source/Core/PolygonGeometry.js | 153 ++++++++++++++++++++++++--------- 1 file changed, 111 insertions(+), 42 deletions(-) diff --git a/Source/Core/PolygonGeometry.js b/Source/Core/PolygonGeometry.js index 318cebbdb507..1df22adce77c 100644 --- a/Source/Core/PolygonGeometry.js +++ b/Source/Core/PolygonGeometry.js @@ -85,45 +85,6 @@ define([ return result; } - var appendTextureCoordinatesOrigin = new Cartesian2(); - var appendTextureCoordinatesCartesian2 = new Cartesian2(); - var appendTextureCoordinatesCartesian3 = new Cartesian3(); - var appendTextureCoordinatesQuaternion = new Quaternion(); - var appendTextureCoordinatesMatrix3 = new Matrix3(); - - function appendTextureCoordinates(mesh, tangentPlane, boundingRectangle, angle) { - var origin = appendTextureCoordinatesOrigin; - origin.x = boundingRectangle.x; - origin.y = boundingRectangle.y; - - var positions = mesh.attributes.position.values; - var length = positions.length; - - var textureCoordinates = new Float32Array(2 * (length / 3)); - var j = 0; - - var rotation = Quaternion.fromAxisAngle(tangentPlane._plane.normal, angle, appendTextureCoordinatesQuaternion); - var textureMatrix = Matrix3.fromQuaternion(rotation, appendTextureCoordinatesMatrix3); - - for ( var i = 0; i < length; i += 3) { - var p = Cartesian3.fromArray(positions, i, appendTextureCoordinatesCartesian3); - Matrix3.multiplyByVector(textureMatrix, p, p); - var st = tangentPlane.projectPointOntoPlane(p, appendTextureCoordinatesCartesian2); - st.subtract(origin, st); - - textureCoordinates[j++] = st.x / boundingRectangle.width; - textureCoordinates[j++] = st.y / boundingRectangle.height; - } - - mesh.attributes.st = new GeometryAttribute({ - componentDatatype : ComponentDatatype.FLOAT, - componentsPerAttribute : 2, - values : textureCoordinates - }); - - return mesh; - } - var createMeshFromPositionsPositions = []; function createMeshFromPositions(ellipsoid, positions, boundingSphere, granularity) { @@ -153,6 +114,16 @@ define([ } var scratchBoundingRectangle = new BoundingRectangle(); + var scratchPosition = new Cartesian3(); + var scratchNormal = new Cartesian3(); + var scratchTangent = new Cartesian3(); + var scratchBinormal = new Cartesian3(); + + var appendTextureCoordinatesOrigin = new Cartesian2(); + var appendTextureCoordinatesCartesian2 = new Cartesian2(); + var appendTextureCoordinatesCartesian3 = new Cartesian3(); + var appendTextureCoordinatesQuaternion = new Quaternion(); + var appendTextureCoordinatesMatrix3 = new Matrix3(); /** * Computes vertices and indices for a polygon on the ellipsoid. The polygon is either defined @@ -318,14 +289,112 @@ define([ attributes.position = mesh.attributes.position; } - if (vertexFormat.st) { + + if (vertexFormat.st || vertexFormat.normal || vertexFormat.tangent || vertexFormat.binormal) { // PERFORMANCE_IDEA: Compute before subdivision, then just interpolate during subdivision. // PERFORMANCE_IDEA: Compute with createMeshFromPositions() for fast path when there's no holes. var cleanedPositions = PolygonPipeline.cleanUp(outerPositions); var tangentPlane = EllipsoidTangentPlane.fromPoints(cleanedPositions, ellipsoid); var boundingRectangle = computeBoundingRectangle(tangentPlane, outerPositions, stRotation, scratchBoundingRectangle); - mesh = appendTextureCoordinates(mesh, tangentPlane, boundingRectangle, stRotation); - attributes.st = mesh.attributes.st; + + var origin = appendTextureCoordinatesOrigin; + origin.x = boundingRectangle.x; + origin.y = boundingRectangle.y; + + var flatPositions = mesh.attributes.position.values; + var length = flatPositions.length; + + var textureCoordinates = vertexFormat.st ? new Float32Array(2 * (length / 3)) : undefined; + var normals = vertexFormat.normal ? new Array(length) : undefined; + var tangents = vertexFormat.tangent ? new Array(length) : undefined; + var binormals = vertexFormat.binormal ? new Array(length) : undefined; + + var textureCoordIndex = 0; + var normalIndex = 0; + var tangentIndex = 0; + var binormalIndex = 0; + + var normal = scratchNormal; + var tangent = scratchTangent; + + var rotation = Quaternion.fromAxisAngle(tangentPlane._plane.normal, stRotation, appendTextureCoordinatesQuaternion); + var textureMatrix = Matrix3.fromQuaternion(rotation, appendTextureCoordinatesMatrix3); + + for (i = 0; i < length; i += 3) { + var position = Cartesian3.fromArray(flatPositions, i, appendTextureCoordinatesCartesian3); + + if (vertexFormat.st) { + var p = Matrix3.multiplyByVector(textureMatrix, position, scratchPosition); + var st = tangentPlane.projectPointOntoPlane(p, appendTextureCoordinatesCartesian2); + Cartesian2.subtract(st, origin, st); + + textureCoordinates[textureCoordIndex++] = st.x / boundingRectangle.width; + textureCoordinates[textureCoordIndex++] = st.y / boundingRectangle.height; + } + + if (vertexFormat.normal) { + normal = ellipsoid.geodeticSurfaceNormal(position, normal); + + normals[normalIndex++] = normal.x; + normals[normalIndex++] = normal.y; + normals[normalIndex++] = normal.z; + } + + if (vertexFormat.tangent) { + ellipsoid.geodeticSurfaceNormal(position, normal); + Cartesian3.cross(Cartesian3.UNIT_Z, normal, tangent); + Matrix3.multiplyByVector(textureMatrix, tangent, tangent); + Cartesian3.normalize(tangent, tangent); + + tangents[tangentIndex++] = tangent.x; + tangents[tangentIndex++] = tangent.y; + tangents[tangentIndex++] = tangent.z; + } + + if (vertexFormat.binormal) { + ellipsoid.geodeticSurfaceNormal(position, normal); + Cartesian3.cross(Cartesian3.UNIT_Z, normal, tangent); + Matrix3.multiplyByVector(textureMatrix, tangent, tangent); + var binormal = Cartesian3.cross(tangent, normal, scratchBinormal); + Cartesian3.normalize(binormal, binormal); + + binormals[binormalIndex++] = binormal.x; + binormals[binormalIndex++] = binormal.y; + binormals[binormalIndex++] = binormal.z; + } + } + + if (vertexFormat.st) { + attributes.st = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 2, + values : textureCoordinates + }); + } + + if (vertexFormat.normal) { + attributes.normal = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : normals + }); + } + + if (vertexFormat.tangent) { + attributes.tangent = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : tangents + }); + } + + if (vertexFormat.binormal) { + attributes.binormal = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : binormals + }); + } } /** From a315aabe6af8609c745fd3945092dba602ca300c Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 3 Jun 2013 17:03:37 -0400 Subject: [PATCH 133/306] Re-order wall positions. --- Source/Core/WallGeometry.js | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/Source/Core/WallGeometry.js b/Source/Core/WallGeometry.js index 811f39059025..591993eccbaf 100644 --- a/Source/Core/WallGeometry.js +++ b/Source/Core/WallGeometry.js @@ -7,11 +7,14 @@ define([ './ComponentDatatype', './DeveloperError', './Ellipsoid', + './EllipsoidTangentPlane', './GeometryAttribute', './GeometryIndices', './Matrix4', + './PolygonPipeline', './PrimitiveType', - './VertexFormat' + './VertexFormat', + './WindingOrder' ], function( defaultValue, BoundingSphere, @@ -20,11 +23,14 @@ define([ ComponentDatatype, DeveloperError, Ellipsoid, + EllipsoidTangentPlane, GeometryAttribute, GeometryIndices, Matrix4, + PolygonPipeline, PrimitiveType, - VertexFormat) { + VertexFormat, + WindingOrder) { "use strict"; var scratchCartographic = new Cartographic(); @@ -91,6 +97,17 @@ define([ throw new DeveloperError('positions and terrain points must have the same length.'); } + wallPositions = PolygonPipeline.cleanUp(wallPositions); + if (wallPositions.length >= 3) { + // Order positions counter-clockwise + var tangentPlane = EllipsoidTangentPlane.fromPoints(wallPositions, ellipsoid); + var positions2D = tangentPlane.projectPointsOntoPlane(wallPositions); + + if (PolygonPipeline.computeWindingOrder2D(positions2D) === WindingOrder.CLOCKWISE) { + wallPositions.reverse(); + } + } + var i; var size = wallPositions.length * 2; From 46c2f335930b794729e93be53e6eb22f005049f2 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 3 Jun 2013 17:39:36 -0400 Subject: [PATCH 134/306] Update and add tests. --- Source/Core/PolygonGeometry.js | 1 - Specs/Core/PolygonGeometrySpec.js | 245 ++++++++++++------------------ 2 files changed, 101 insertions(+), 145 deletions(-) diff --git a/Source/Core/PolygonGeometry.js b/Source/Core/PolygonGeometry.js index 1df22adce77c..f6223ca34653 100644 --- a/Source/Core/PolygonGeometry.js +++ b/Source/Core/PolygonGeometry.js @@ -289,7 +289,6 @@ define([ attributes.position = mesh.attributes.position; } - if (vertexFormat.st || vertexFormat.normal || vertexFormat.tangent || vertexFormat.binormal) { // PERFORMANCE_IDEA: Compute before subdivision, then just interpolate during subdivision. // PERFORMANCE_IDEA: Compute with createMeshFromPositions() for fast path when there's no holes. diff --git a/Specs/Core/PolygonGeometrySpec.js b/Specs/Core/PolygonGeometrySpec.js index f8e5fb2d30c8..ee53332a04be 100644 --- a/Specs/Core/PolygonGeometrySpec.js +++ b/Specs/Core/PolygonGeometrySpec.js @@ -1,96 +1,122 @@ /*global defineSuite*/ defineSuite([ 'Core/PolygonGeometry', - 'Specs/createContext', - 'Specs/destroyContext', - 'Specs/createCamera', - 'Specs/createFrameState', - 'Specs/frameState', - 'Specs/pick', - 'Specs/render', 'Core/Cartesian3', 'Core/Cartographic', 'Core/Ellipsoid', - 'Core/Matrix4', 'Core/Math', - 'Core/JulianDate', - 'Renderer/BufferUsage', - 'Renderer/ClearCommand', - 'Scene/Material', - 'Scene/Appearance', - 'Scene/Primitive', - 'Scene/SceneMode' + 'Core/VertexFormat' ], function( PolygonGeometry, - createContext, - destroyContext, - createCamera, - createFrameState, - frameState, - pick, - render, Cartesian3, Cartographic, Ellipsoid, - Matrix4, CesiumMath, - JulianDate, - BufferUsage, - ClearCommand, - Material, - Appearance, - Primitive, - SceneMode) { + VertexFormat) { "use strict"; /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/ - var context; - var polygon; - var us; - - beforeAll(function() { - context = createContext(); + it('throws without positions or hierarchy', function() { + expect(function() { + return new PolygonGeometry(); + }).toThrow(); }); - afterAll(function() { - destroyContext(context); + it('throws with less than three positions', function() { + expect(function() { + return new PolygonGeometry({ positions : [new Cartesian3()] }); + }).toThrow(); }); - beforeEach(function() { - polygon = createPolygonGeometry(); + it('throws with polygon hierarchy with less than three positions', function() { + var hierarchy = { + positions : Ellipsoid.WGS84.cartographicArrayToCartesianArray([ + new Cartographic() + ]) + }; - us = context.getUniformState(); - us.update(createFrameState(createCamera(context, new Cartesian3(1.02, 0.0, 0.0), Cartesian3.ZERO, Cartesian3.UNIT_Z))); + expect(function() { + return new PolygonGeometry({ polygonHierarchy : hierarchy }); + }).toThrow(); }); - afterEach(function() { - polygon = undefined; - us = undefined; + it('throws due to duplicate positions', function() { + var ellipsoid = Ellipsoid.UNIT_SPHERE; + + expect(function() { + return new PolygonGeometry({ + positions : [ + ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(0.0, 0.0, 0.0)), + ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(0.0, 0.0, 0.0)), + ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(0.0, 0.0, 0.0)) + ], + ellipsoid : ellipsoid + }); + }).toThrow(); }); - function createPolygonGeometry() { + it('throws due to duplicate hierarchy positions', function() { var ellipsoid = Ellipsoid.UNIT_SPHERE; + var hierarchy = { + positions : ellipsoid.cartographicArrayToCartesianArray([ + Cartographic.fromDegrees(1.0, 1.0, 0.0), + Cartographic.fromDegrees(1.0, 1.0, 0.0), + Cartographic.fromDegrees(1.0, 1.0, 0.0) + ]), + holes : [{ + positions : ellipsoid.cartographicArrayToCartesianArray([ + Cartographic.fromDegrees(0.0, 0.0, 0.0), + Cartographic.fromDegrees(0.0, 0.0, 0.0), + Cartographic.fromDegrees(0.0, 0.0, 0.0) + ]) + }] + }; + expect(function() { + return new PolygonGeometry({ + polygonHierarchy : hierarchy, + ellipsoid : ellipsoid + }); + }).toThrow(); + }); + + it('computes positions', function() { var p = new PolygonGeometry({ - positions : [ - ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-50.0, -50.0, 0.0)), - ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(50.0, -50.0, 0.0)), - ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(50.0, 50.0, 0.0)), - ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-50.0, 50.0, 0.0)) - ], - ellipsoid : ellipsoid + vertexformat : VertexFormat.POSITION_ONLY, + positions : Ellipsoid.WGS84.cartographicArrayToCartesianArray([ + Cartographic.fromDegrees(-50.0, -50.0, 0.0), + Cartographic.fromDegrees(50.0, -50.0, 0.0), + Cartographic.fromDegrees(50.0, 50.0, 0.0), + Cartographic.fromDegrees(-50.0, 50.0, 0.0) + ]), + granularity : CesiumMath.PI_OVER_THREE }); - return p; - } + expect(p.attributes.position.values.length).toEqual(3 * 11); + expect(p.indexLists[0].values.length).toEqual(3 * 14); + }); - it('create throws with less than three positions', function() { - expect(function() { - return new PolygonGeometry({ positions : [new Cartesian3()] }); - }).toThrow(); + it('computes all attributes', function() { + var p = new PolygonGeometry({ + vertexFormat : VertexFormat.ALL, + positions : Ellipsoid.WGS84.cartographicArrayToCartesianArray([ + Cartographic.fromDegrees(-50.0, -50.0, 0.0), + Cartographic.fromDegrees(50.0, -50.0, 0.0), + Cartographic.fromDegrees(50.0, 50.0, 0.0), + Cartographic.fromDegrees(-50.0, 50.0, 0.0) + ]), + granularity : CesiumMath.PI_OVER_THREE + }); + + expect(p.attributes.position.values.length).toEqual(3 * 11); + expect(p.attributes.st.values.length).toEqual(2 * 11); + expect(p.attributes.normal.values.length).toEqual(3 * 11); + expect(p.attributes.tangent.values.length).toEqual(3 * 11); + expect(p.attributes.binormal.values.length).toEqual(3 * 11); + expect(p.indexLists[0].values.length).toEqual(3 * 14); }); - it('create polygon from hierarchy', function() { + it('creates a polygon from hierarchy', function() { var hierarchy = { positions : Ellipsoid.WGS84.cartographicArrayToCartesianArray([ Cartographic.fromDegrees(-124.0, 35.0, 0.0), @@ -116,10 +142,17 @@ defineSuite([ }] }; - var p = new PolygonGeometry({ polygonHierarchy : hierarchy }); + var p = new PolygonGeometry({ + vertexformat : VertexFormat.POSITION_ONLY, + polygonHierarchy : hierarchy, + granularity : CesiumMath.PI_OVER_THREE + }); + + expect(p.attributes.position.values.length).toEqual(3 * 14); + expect(p.indexLists[0].values.length).toEqual(3 * 10); }); - it('create polygon from clockwise hierarchy', function() { + it('creates a polygon from clockwise hierarchy', function() { var hierarchy = { positions : Ellipsoid.WGS84.cartographicArrayToCartesianArray([ Cartographic.fromDegrees(-124.0, 35.0, 0.0), @@ -145,90 +178,14 @@ defineSuite([ }] }; - var p = new PolygonGeometry({ polygonHierarchy : hierarchy }); - }); - - it('create from PolygonHierarchy throws with less than three positions', function() { - var hierarchy = { - positions : Ellipsoid.WGS84.cartographicArrayToCartesianArray([ - new Cartographic() - ]) - }; - - expect(function() { - return new PolygonGeometry({ polygonHierarchy : hierarchy }); - }).toThrow(); - }); - - it('renders', function() { - // This test fails in Chrome if a breakpoint is set inside this function. Strange. - - var material = Material.fromType(undefined, Material.ColorType); - material.uniforms.color = { red : 1.0, green : 0.0, blue : 0.0, alpha : 1.0 }; - var appearance = new Appearance({ material : material }); - - var primitive = new Primitive({ - geometries : polygon, - appearance : appearance - }); - - ClearCommand.ALL.execute(context); - expect(context.readPixels()).toEqual([0, 0, 0, 0]); - - render(context, frameState, primitive); - expect(context.readPixels()).not.toEqual([0, 0, 0, 0]); - }); - - it('does not render when show is false', function() { - var material = Material.fromType(undefined, Material.ColorType); - material.uniforms.color = { red : 1.0, green : 0.0, blue : 0.0, alpha : 1.0 }; - var appearance = new Appearance({ material : material }); - var primitive = new Primitive({ - geometries : polygon, - appearance : appearance + var p = new PolygonGeometry({ + vertexformat : VertexFormat.POSITION_ONLY, + polygonHierarchy : hierarchy, + granularity : CesiumMath.PI_OVER_THREE }); - primitive.show = false; - - expect(render(context, frameState, primitive)).toEqual(0); - }); - it('cannot create due to duplicate positions', function() { - var ellipsoid = Ellipsoid.UNIT_SPHERE; - - expect(function() { - polygon = new PolygonGeometry({ - positions : [ - ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(0.0, 0.0, 0.0)), - ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(0.0, 0.0, 0.0)), - ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(0.0, 0.0, 0.0)) - ], - ellipsoid : ellipsoid - }); - }).toThrow(); + expect(p.attributes.position.values.length).toEqual(3 * 14); + expect(p.indexLists[0].values.length).toEqual(3 * 10); }); - it('cannot create due to duplicate hierarchy positions', function() { - var ellipsoid = Ellipsoid.UNIT_SPHERE; - var hierarchy = { - positions : ellipsoid.cartographicArrayToCartesianArray([ - Cartographic.fromDegrees(1.0, 1.0, 0.0), - Cartographic.fromDegrees(1.0, 1.0, 0.0), - Cartographic.fromDegrees(1.0, 1.0, 0.0) - ]), - holes : [{ - positions : ellipsoid.cartographicArrayToCartesianArray([ - Cartographic.fromDegrees(0.0, 0.0, 0.0), - Cartographic.fromDegrees(0.0, 0.0, 0.0), - Cartographic.fromDegrees(0.0, 0.0, 0.0) - ]) - }] - }; - - expect(function() { - polygon = new PolygonGeometry({ - polygonHierarchy : hierarchy, - ellipsoid : ellipsoid - }); - }).toThrow(); - }); }, 'WebGL'); From d4dac9e298ec5d0c1909ed65e8d7fc2882403bc8 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Mon, 3 Jun 2013 17:54:18 -0400 Subject: [PATCH 135/306] Wall fixes --- Apps/CesiumViewer/CesiumViewer.js | 21 +++++++++------------ Source/Core/PolylinePipeline.js | 28 ++++++++++++++++++++++++++++ Source/Core/WallGeometry.js | 4 +++- 3 files changed, 40 insertions(+), 13 deletions(-) diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index 16f0102a1c5e..bfb43ab8483c 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -23,7 +23,6 @@ define([ 'Core/ScreenSpaceEventHandler', 'Core/ScreenSpaceEventType', 'Core/WallGeometry', - 'Renderer/BlendingState', 'Scene/Primitive', 'Scene/Appearance', 'Scene/ClosedTranslucentAppearance', @@ -56,7 +55,6 @@ define([ ScreenSpaceEventHandler, ScreenSpaceEventType, WallGeometry, - BlendingState, Primitive, Appearance, ClosedTranslucentAppearance, @@ -245,6 +243,7 @@ define([ })); var wall = new WallGeometry({ + vertexFormat : VertexFormat.ALL, positions : ellipsoid.cartographicArrayToCartesianArray([ Cartographic.fromDegrees(-125.0, 37.0, 100000.0), Cartographic.fromDegrees(-125.0, 38.0, 100000.0), @@ -254,18 +253,16 @@ define([ ]), pickData : 'wall' }); - var wallAppearance = new Appearance({ - renderState : { - depthTest : { - enabled : true - }, - depthMask : false, - blending : BlendingState.ALPHA_BLEND - } - }); widget.scene.getPrimitives().add(new Primitive({ geometries : wall, - appearance : wallAppearance + appearance : new Appearance({ + material : Material.fromType(scene.getContext(), 'Wood'), + renderState : { + depthTest : { + enabled : true + } + } + }) })); var handler = new ScreenSpaceEventHandler(scene.getCanvas()); diff --git a/Source/Core/PolylinePipeline.js b/Source/Core/PolylinePipeline.js index 51e1d4750a07..a8e5549cab48 100644 --- a/Source/Core/PolylinePipeline.js +++ b/Source/Core/PolylinePipeline.js @@ -112,5 +112,33 @@ define([ }; }; + /** + * DOC_TBA + */ + PolylinePipeline.cleanUp = function(positions) { + if (typeof positions === 'undefined') { + throw new DeveloperError('positions is required.'); + } + + var length = positions.length; + if (length < 2) { + return positions.slice(0); + } + + var cleanedPositions = []; + cleanedPositions.push(positions[0]); + + for (var i = 1; i < length; ++i) { + var v0 = positions[i - 1]; + var v1 = positions[i]; + + if (!v0.equals(v1)) { + cleanedPositions.push(v1); // Shallow copy! + } + } + + return cleanedPositions; + }; + return PolylinePipeline; }); diff --git a/Source/Core/WallGeometry.js b/Source/Core/WallGeometry.js index 591993eccbaf..471fc6c75365 100644 --- a/Source/Core/WallGeometry.js +++ b/Source/Core/WallGeometry.js @@ -11,6 +11,7 @@ define([ './GeometryAttribute', './GeometryIndices', './Matrix4', + './PolylinePipeline', './PolygonPipeline', './PrimitiveType', './VertexFormat', @@ -27,6 +28,7 @@ define([ GeometryAttribute, GeometryIndices, Matrix4, + PolylinePipeline, PolygonPipeline, PrimitiveType, VertexFormat, @@ -97,7 +99,7 @@ define([ throw new DeveloperError('positions and terrain points must have the same length.'); } - wallPositions = PolygonPipeline.cleanUp(wallPositions); + wallPositions = PolylinePipeline.cleanUp(wallPositions, false); if (wallPositions.length >= 3) { // Order positions counter-clockwise var tangentPlane = EllipsoidTangentPlane.fromPoints(wallPositions, ellipsoid); From cda0e3f8678e82d28506707d304b2311fba6f096 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Mon, 3 Jun 2013 17:55:30 -0400 Subject: [PATCH 136/306] Removed unused parameter --- Source/Core/WallGeometry.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Core/WallGeometry.js b/Source/Core/WallGeometry.js index 471fc6c75365..cb3360cef696 100644 --- a/Source/Core/WallGeometry.js +++ b/Source/Core/WallGeometry.js @@ -99,7 +99,7 @@ define([ throw new DeveloperError('positions and terrain points must have the same length.'); } - wallPositions = PolylinePipeline.cleanUp(wallPositions, false); + wallPositions = PolylinePipeline.cleanUp(wallPositions); if (wallPositions.length >= 3) { // Order positions counter-clockwise var tangentPlane = EllipsoidTangentPlane.fromPoints(wallPositions, ellipsoid); From e9c80dfe80b4436483eaec8c6877fe2188f86862 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 3 Jun 2013 19:20:47 -0400 Subject: [PATCH 137/306] Updates based on review. --- Source/Core/PolygonGeometry.js | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/Source/Core/PolygonGeometry.js b/Source/Core/PolygonGeometry.js index f6223ca34653..5bb3132d6598 100644 --- a/Source/Core/PolygonGeometry.js +++ b/Source/Core/PolygonGeometry.js @@ -303,7 +303,7 @@ define([ var flatPositions = mesh.attributes.position.values; var length = flatPositions.length; - var textureCoordinates = vertexFormat.st ? new Float32Array(2 * (length / 3)) : undefined; + var textureCoordinates = vertexFormat.st ? new Array(2 * (length / 3)) : undefined; var normals = vertexFormat.normal ? new Array(length) : undefined; var tangents = vertexFormat.tangent ? new Array(length) : undefined; var binormals = vertexFormat.binormal ? new Array(length) : undefined; @@ -340,7 +340,10 @@ define([ } if (vertexFormat.tangent) { - ellipsoid.geodeticSurfaceNormal(position, normal); + if (!vertexFormat.normal) { + ellipsoid.geodeticSurfaceNormal(position, normal); + } + Cartesian3.cross(Cartesian3.UNIT_Z, normal, tangent); Matrix3.multiplyByVector(textureMatrix, tangent, tangent); Cartesian3.normalize(tangent, tangent); @@ -351,9 +354,15 @@ define([ } if (vertexFormat.binormal) { - ellipsoid.geodeticSurfaceNormal(position, normal); - Cartesian3.cross(Cartesian3.UNIT_Z, normal, tangent); - Matrix3.multiplyByVector(textureMatrix, tangent, tangent); + if (!vertexFormat.normal) { + ellipsoid.geodeticSurfaceNormal(position, normal); + } + + if (!vertexFormat.tangent) { + Cartesian3.cross(Cartesian3.UNIT_Z, normal, tangent); + Matrix3.multiplyByVector(textureMatrix, tangent, tangent); + } + var binormal = Cartesian3.cross(tangent, normal, scratchBinormal); Cartesian3.normalize(binormal, binormal); From 71d61c8484d1882b354ca75cdda97c5febbb33f5 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Tue, 4 Jun 2013 13:31:03 -0400 Subject: [PATCH 138/306] Start of instancing --- Apps/CesiumViewer/CesiumViewer.js | 181 +++++++++++++++------------- Source/Core/BoxGeometry.js | 29 ----- Source/Core/CircleGeometry.js | 27 ----- Source/Core/EllipseGeometry.js | 29 ----- Source/Core/EllipsoidGeometry.js | 27 ----- Source/Core/ExtentGeometry.js | 29 ----- Source/Core/Geometry.js | 45 +------ Source/Core/GeometryFilters.js | 107 ++++++++-------- Source/Core/GeometryInstance.js | 53 ++++++++ Source/Core/PolygonGeometry.js | 33 +---- Source/Core/PolygonPipeline.js | 18 ++- Source/Core/WallGeometry.js | 51 ++------ Source/Scene/Polygon.js | 7 +- Source/Scene/Primitive.js | 99 +++++++-------- Specs/Core/BoxGeometrySpec.js | 2 - Specs/Core/EllipsoidGeometrySpec.js | 2 - Specs/Core/GeometryFiltersSpec.js | 130 ++++++++++---------- Specs/Core/PolygonGeometrySpec.js | 34 +++--- 18 files changed, 381 insertions(+), 522 deletions(-) create mode 100644 Source/Core/GeometryInstance.js diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index bfb43ab8483c..d9845d913d69 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -12,6 +12,7 @@ define([ 'Core/Matrix4', 'Core/Ellipsoid', 'Core/Extent', + 'Core/GeometryInstance', 'Core/ExtentGeometry', 'Core/EllipseGeometry', 'Core/EllipsoidGeometry', @@ -44,6 +45,7 @@ define([ Matrix4, Ellipsoid, Extent, + GeometryInstance, ExtentGeometry, EllipseGeometry, EllipsoidGeometry, @@ -84,54 +86,61 @@ define([ widget.startup(); widget.fullscreen.viewModel.fullscreenElement(document.body); + // For debug. This kills performance. + widget.scene.getContext().setThrowOnWebGLError(true); + var scene = widget.scene; var ellipsoid = widget.centralBody.getEllipsoid(); - var mesh = new ExtentGeometry({ - vertexFormat : VertexFormat.POSITION_AND_NORMAL, - extent : new Extent( - CesiumMath.toRadians(-180.0), - CesiumMath.toRadians(50.0), - CesiumMath.toRadians(180.0), - CesiumMath.toRadians(90.0)), - granularity : 0.006, // More than 64K vertices + var mesh = new GeometryInstance({ + geometry : new ExtentGeometry({ + vertexFormat : VertexFormat.POSITION_AND_NORMAL, + extent : new Extent( + CesiumMath.toRadians(-180.0), + CesiumMath.toRadians(50.0), + CesiumMath.toRadians(180.0), + CesiumMath.toRadians(90.0)), + granularity : 0.006 // More than 64K vertices + }), pickData : 'mesh', color : Color.CORNFLOWERBLUE }); - - var mesh2 = new EllipsoidGeometry({ - vertexFormat : VertexFormat.POSITION_AND_NORMAL, - ellipsoid : new Ellipsoid(500000.0, 500000.0, 1000000.0), + var mesh2 = new GeometryInstance({ + geometry : new EllipsoidGeometry({ + vertexFormat : VertexFormat.POSITION_AND_NORMAL, + ellipsoid : new Ellipsoid(500000.0, 500000.0, 1000000.0) + }), modelMatrix : Matrix4.multiplyByTranslation(Transforms.eastNorthUpToFixedFrame( - ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-95.59777, 40.03883))), new Cartesian3(0.0, 0.0, 500000.0)), + ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-95.59777, 40.03883))), new Cartesian3(0.0, 0.0, 500000.0)), pickData : 'mesh2', color : Color.AQUAMARINE.clone() }); mesh2.color.alpha = 0.5; - - var mesh3 = new BoxGeometry({ - vertexFormat : VertexFormat.POSITION_AND_NORMAL, - dimensions : new Cartesian3(1000000.0, 1000000.0, 2000000.0), + var mesh3 = new GeometryInstance({ + geometry : new BoxGeometry({ + vertexFormat : VertexFormat.POSITION_AND_NORMAL, + dimensions : new Cartesian3(1000000.0, 1000000.0, 2000000.0) + }), modelMatrix : Matrix4.multiplyByTranslation(Transforms.eastNorthUpToFixedFrame( ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-75.59777, 40.03883))), new Cartesian3(0.0, 0.0, 3000000.0)), pickData : 'mesh3', color : Color.BLANCHEDALMOND }); - - var mesh4 = new EllipseGeometry({ - vertexFormat : VertexFormat.POSITION_AND_NORMAL, - ellipsoid : ellipsoid, - center : ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-100, 20)), - semiMinorAxis : 500000.0, - semiMajorAxis : 1000000.0, - bearing : CesiumMath.PI_OVER_FOUR, - height : 1000000.0, + var mesh4 = new GeometryInstance({ + geometry : new EllipseGeometry({ + vertexFormat : VertexFormat.POSITION_AND_NORMAL, + ellipsoid : ellipsoid, + center : ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-100, 20)), + semiMinorAxis : 500000.0, + semiMajorAxis : 1000000.0, + bearing : CesiumMath.PI_OVER_FOUR, + height : 1000000.0 + }), pickData : 'mesh4', color : Color.LIME }); - var primitive = new Primitive({ - geometries : [mesh, mesh2, mesh3, mesh4], + geometryInstances : [mesh, mesh2, mesh3, mesh4], appearance : new PerGeometryColorClosedTranslucentAppearance() }); scene.getPrimitives().add(primitive); @@ -170,91 +179,93 @@ define([ material : m, renderState : rs }); - - var mesh5 = new EllipsoidGeometry({ - vertexFormat : VertexFormat.ALL, - ellipsoid : new Ellipsoid(1000000.0, 500000.0, 500000.0), + var mesh5 = new GeometryInstance({ + geometry : new EllipsoidGeometry({ + vertexFormat : VertexFormat.ALL, + ellipsoid : new Ellipsoid(1000000.0, 500000.0, 500000.0) + }), modelMatrix : Matrix4.multiplyByTranslation(Transforms.eastNorthUpToFixedFrame( - ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-75.59777, 40.03883))), new Cartesian3(0.0, 0.0, 4500000.0)), + ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-75.59777, 40.03883))), new Cartesian3(0.0, 0.0, 4500000.0)), pickData : 'mesh5' }); - - var primitive2 = new Primitive({ - geometries : mesh5, + scene.getPrimitives().add(new Primitive({ + geometryInstances : mesh5, appearance :appearance, vertexCacheOptimize : false, - releaseGeometries : true, + releasegeometryInstances : true, transformToWorldCoordinates : false - }); - scene.getPrimitives().add(primitive2); + })); - var polygonGeometry = new PolygonGeometry({ - vertexFormat : VertexFormat.POSITION_AND_ST, + var polygonGeometry = new GeometryInstance({ + geometry : new PolygonGeometry({ + vertexFormat : VertexFormat.POSITION_AND_ST, /* - positions : ellipsoid.cartographicArrayToCartesianArray([ - Cartographic.fromDegrees(-72.0, 40.0), - Cartographic.fromDegrees(-70.0, 35.0), - Cartographic.fromDegrees(-75.0, 30.0), - Cartographic.fromDegrees(-70.0, 30.0), - Cartographic.fromDegrees(-68.0, 40.0) - ]), -*/ - polygonHierarchy : { positions : ellipsoid.cartographicArrayToCartesianArray([ - Cartographic.fromDegrees(-109.0, 30.0), - Cartographic.fromDegrees(-95.0, 30.0), - Cartographic.fromDegrees(-95.0, 40.0), - Cartographic.fromDegrees(-109.0, 40.0) + Cartographic.fromDegrees(-72.0, 40.0), + Cartographic.fromDegrees(-70.0, 35.0), + Cartographic.fromDegrees(-75.0, 30.0), + Cartographic.fromDegrees(-70.0, 30.0), + Cartographic.fromDegrees(-68.0, 40.0) ]), - holes : [{ +*/ + polygonHierarchy : { positions : ellipsoid.cartographicArrayToCartesianArray([ - Cartographic.fromDegrees(-107.0, 31.0), - Cartographic.fromDegrees(-107.0, 39.0), - Cartographic.fromDegrees(-97.0, 39.0), - Cartographic.fromDegrees(-97.0, 31.0) + Cartographic.fromDegrees(-109.0, 30.0), + Cartographic.fromDegrees(-95.0, 30.0), + Cartographic.fromDegrees(-95.0, 40.0), + Cartographic.fromDegrees(-109.0, 40.0) ]), holes : [{ positions : ellipsoid.cartographicArrayToCartesianArray([ - Cartographic.fromDegrees(-105.0, 33.0), - Cartographic.fromDegrees(-99.0, 33.0), - Cartographic.fromDegrees(-99.0, 37.0), - Cartographic.fromDegrees(-105.0, 37.0) - ]), + Cartographic.fromDegrees(-107.0, 31.0), + Cartographic.fromDegrees(-107.0, 39.0), + Cartographic.fromDegrees(-97.0, 39.0), + Cartographic.fromDegrees(-97.0, 31.0) + ]), holes : [{ positions : ellipsoid.cartographicArrayToCartesianArray([ - Cartographic.fromDegrees(-103.0, 34.0), - Cartographic.fromDegrees(-101.0, 34.0), - Cartographic.fromDegrees(-101.0, 36.0), - Cartographic.fromDegrees(-103.0, 36.0) - ]) + Cartographic.fromDegrees(-105.0, 33.0), + Cartographic.fromDegrees(-99.0, 33.0), + Cartographic.fromDegrees(-99.0, 37.0), + Cartographic.fromDegrees(-105.0, 37.0) + ]), + holes : [{ + positions : ellipsoid.cartographicArrayToCartesianArray([ + Cartographic.fromDegrees(-103.0, 34.0), + Cartographic.fromDegrees(-101.0, 34.0), + Cartographic.fromDegrees(-101.0, 36.0), + Cartographic.fromDegrees(-103.0, 36.0) + ]) + }] }] }] - }] - }, - pickData : 'polygon3', - stRotation : 0.523598776 + }, + stRotation : 0.523598776 + }), + pickData : 'polygon3' }); - widget.scene.getPrimitives().add(new Primitive({ - geometries : polygonGeometry, + geometryInstances : polygonGeometry, appearance : new EllipsoidSurfaceAppearance({ material : Material.fromType(scene.getContext(), 'Stripe') }) })); - var wall = new WallGeometry({ - vertexFormat : VertexFormat.ALL, - positions : ellipsoid.cartographicArrayToCartesianArray([ - Cartographic.fromDegrees(-125.0, 37.0, 100000.0), - Cartographic.fromDegrees(-125.0, 38.0, 100000.0), - Cartographic.fromDegrees(-120.0, 38.0, 100000.0), - Cartographic.fromDegrees(-120.0, 37.0, 100000.0), - Cartographic.fromDegrees(-125.0, 37.0, 100000.0) - ]), + var wall = new GeometryInstance({ + geometry : new WallGeometry({ + vertexFormat : VertexFormat.ALL, + positions : ellipsoid.cartographicArrayToCartesianArray([ + Cartographic.fromDegrees(-125.0, 37.0, 100000.0), + Cartographic.fromDegrees(-125.0, 38.0, 100000.0), + Cartographic.fromDegrees(-120.0, 38.0, 100000.0), + Cartographic.fromDegrees(-120.0, 37.0, 100000.0), + Cartographic.fromDegrees(-125.0, 37.0, 100000.0) + ]) + }), pickData : 'wall' }); widget.scene.getPrimitives().add(new Primitive({ - geometries : wall, + geometryInstances : wall, appearance : new Appearance({ material : Material.fromType(scene.getContext(), 'Wood'), renderState : { diff --git a/Source/Core/BoxGeometry.js b/Source/Core/BoxGeometry.js index 84df64e53e16..2abb516fbfd8 100644 --- a/Source/Core/BoxGeometry.js +++ b/Source/Core/BoxGeometry.js @@ -2,7 +2,6 @@ define([ './DeveloperError', './Cartesian3', - './Matrix4', './ComponentDatatype', './PrimitiveType', './defaultValue', @@ -13,7 +12,6 @@ define([ ], function( DeveloperError, Cartesian3, - Matrix4, ComponentDatatype, PrimitiveType, defaultValue, @@ -33,9 +31,6 @@ define([ * @param {Cartesian3} [options.maximumCorner] The maximum x, y, and z coordinates of the box. * @param {Cartesian3} [options.dimensions=new Cartesian3(1.0, 1.0, 1.0)] The width, depth, and height of the box stored in the x, y, and z coordinates of the Cartesian3, respectively. * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed. - * @param {Matrix4} [options.modelMatrix] The model matrix for this box. - * @param {Color} [options.color] The color of the geometry when a per-geometry color appearance is used. - * @param {DOC_TBA} [options.pickData] DOC_TBA * * @exception {DeveloperError} All dimensions components must be greater than or equal to zero. * @@ -72,8 +67,6 @@ define([ var attributes = {}; var indexLists = []; -// TODO: use typed arrays - if (vertexFormat !== VertexFormat.POSITION_ONLY) { if (vertexFormat.position) { @@ -387,28 +380,6 @@ define([ * @type BoundingSphere */ this.boundingSphere = new BoundingSphere(new Cartesian3(), max.subtract(min).magnitude() * 0.5); - - /** - * The 4x4 transformation matrix that transforms the geometry from model to world coordinates. - * When this is the identity matrix, the geometry is drawn in world coordinates, i.e., Earth's WGS84 coordinates. - * Local reference frames can be used by providing a different transformation matrix, like that returned - * by {@link Transforms.eastNorthUpToFixedFrame}. - * - * @type Matrix4 - */ - this.modelMatrix = defaultValue(options.modelMatrix, Matrix4.IDENTITY.clone()); - - /** - * The color of the geometry when a per-geometry color appearance is used. - * - * @type Color - */ - this.color = options.color; - - /** - * DOC_TBA - */ - this.pickData = options.pickData; }; return BoxGeometry; diff --git a/Source/Core/CircleGeometry.js b/Source/Core/CircleGeometry.js index 7abf74d72e30..fae6335ce145 100644 --- a/Source/Core/CircleGeometry.js +++ b/Source/Core/CircleGeometry.js @@ -23,9 +23,6 @@ define([ * @param {Number} [options.height=0.0] The height above the ellipsoid. * @param {Number} [options.granularity=0.02] The angular distance between points on the circle in radians. * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed. - * @param {Matrix4} [options.modelMatrix] The model matrix for this ellipsoid. - * @param {Color} [options.color] The color of the geometry when a per-geometry color appearance is used. - * @param {DOC_TBA} [options.pickData] DOC_TBA * * @exception {DeveloperError} center is required. * @exception {DeveloperError} radius is required. @@ -79,30 +76,6 @@ define([ * @type BoundingSphere */ this.boundingSphere = ellipseGeometry.boundingSphere; - - /** - * The 4x4 transformation matrix that transforms the geometry from model to world coordinates. - * When this is the identity matrix, the geometry is drawn in world coordinates, i.e., Earth's WGS84 coordinates. - * Local reference frames can be used by providing a different transformation matrix, like that returned - * by {@link Transforms.eastNorthUpToFixedFrame}. - * - * @type Matrix4 - * - * @see Transforms.eastNorthUpToFixedFrame - */ - this.modelMatrix = ellipseGeometry.modelMatrix; - - /** - * The color of the geometry when a per-geometry color appearance is used. - * - * @type Color - */ - this.color = options.color; - - /** - * DOC_TBA - */ - this.pickData = ellipseGeometry.pickData; }; return CircleGeometry; diff --git a/Source/Core/EllipseGeometry.js b/Source/Core/EllipseGeometry.js index 0f237a00f091..3fc22c45c88a 100644 --- a/Source/Core/EllipseGeometry.js +++ b/Source/Core/EllipseGeometry.js @@ -10,7 +10,6 @@ define([ './GeometryIndices', './Math', './Matrix3', - './Matrix4', './PrimitiveType', './Quaternion', './VertexFormat' @@ -25,7 +24,6 @@ define([ GeometryIndices, CesiumMath, Matrix3, - Matrix4, PrimitiveType, Quaternion, VertexFormat) { @@ -81,9 +79,6 @@ define([ * @param {Number} [options.bearing=0.0] The angle from north (clockwise) in radians. The default is zero. * @param {Number} [options.granularity=0.02] The angular distance between points on the ellipse in radians. * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed. - * @param {Matrix4} [options.modelMatrix] The model matrix for this ellipsoid. - * @param {Color} [options.color] The color of the geometry when a per-geometry color appearance is used. - * @param {DOC_TBA} [options.pickData] DOC_TBA * * @exception {DeveloperError} center is required. * @exception {DeveloperError} semiMajorAxis is required. @@ -452,30 +447,6 @@ define([ * @type BoundingSphere */ this.boundingSphere = new BoundingSphere(center, semiMajorAxis); - - /** - * The 4x4 transformation matrix that transforms the geometry from model to world coordinates. - * When this is the identity matrix, the geometry is drawn in world coordinates, i.e., Earth's WGS84 coordinates. - * Local reference frames can be used by providing a different transformation matrix, like that returned - * by {@link Transforms.eastNorthUpToFixedFrame}. - * - * @type Matrix4 - * - * @see Transforms.eastNorthUpToFixedFrame - */ - this.modelMatrix = defaultValue(options.modelMatrix, Matrix4.IDENTITY.clone()); - - /** - * The color of the geometry when a per-geometry color appearance is used. - * - * @type Color - */ - this.color = options.color; - - /** - * DOC_TBA - */ - this.pickData = options.pickData; }; return EllipseGeometry; diff --git a/Source/Core/EllipsoidGeometry.js b/Source/Core/EllipsoidGeometry.js index 50c03174545c..e6324d935e49 100644 --- a/Source/Core/EllipsoidGeometry.js +++ b/Source/Core/EllipsoidGeometry.js @@ -4,7 +4,6 @@ define([ './DeveloperError', './Cartesian3', './Math', - './Matrix4', './Ellipsoid', './ComponentDatatype', './PrimitiveType', @@ -17,7 +16,6 @@ define([ DeveloperError, Cartesian3, CesiumMath, - Matrix4, Ellipsoid, ComponentDatatype, PrimitiveType, @@ -123,9 +121,6 @@ define([ * @param {Ellipsoid} [options.ellipsoi=Ellipsoid.UNIT_SPHERE] The ellipsoid used to create vertex attributes. * @param {Number} [options.numberOfPartitions=32] The number of times to partition the ellipsoid in a plane formed by two radii in a single quadrant. * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed. - * @param {Matrix4} [options.modelMatrix] The model matrix for this ellipsoid. - * @param {Color} [options.color] The color of the geometry when a per-geometry color appearance is used. - * @param {DOC_TBA} [options.pickData] DOC_TBA * * @exception {DeveloperError} options.numberOfPartitions must be greater than zero. * @@ -336,28 +331,6 @@ define([ * @type BoundingSphere */ this.boundingSphere = BoundingSphere.fromEllipsoid(ellipsoid); - - /** - * The 4x4 transformation matrix that transforms the geometry from model to world coordinates. - * When this is the identity matrix, the geometry is drawn in world coordinates, i.e., Earth's WGS84 coordinates. - * Local reference frames can be used by providing a different transformation matrix, like that returned - * by {@link Transforms.eastNorthUpToFixedFrame}. - * - * @type Matrix4 - */ - this.modelMatrix = defaultValue(options.modelMatrix, Matrix4.IDENTITY.clone()); - - /** - * The color of the geometry when a per-geometry color appearance is used. - * - * @type Color - */ - this.color = options.color; - - /** - * DOC_TBA - */ - this.pickData = options.pickData; }; return EllipsoidGeometry; diff --git a/Source/Core/ExtentGeometry.js b/Source/Core/ExtentGeometry.js index 444439af85ad..daa309d15266 100644 --- a/Source/Core/ExtentGeometry.js +++ b/Source/Core/ExtentGeometry.js @@ -14,7 +14,6 @@ define([ './GeometryIndices', './Math', './Matrix2', - './Matrix4', './PrimitiveType', './VertexFormat' ], function( @@ -32,7 +31,6 @@ define([ GeometryIndices, CesiumMath, Matrix2, - Matrix4, PrimitiveType, VertexFormat) { "use strict"; @@ -67,9 +65,6 @@ define([ * @param {Number} [options.granularity=CesiumMath.toRadians(1.0)] The distance, in radians, between each latitude and longitude. Determines the number of positions in the buffer. * @param {Number} [options.surfaceHeight=0.0] The height from the surface of the ellipsoid. * @param {Number} [options.rotation=0.0] The rotation of the extent in radians. A positive rotation is counter-clockwise. - * @param {Matrix4} [options.modelMatrix] The model matrix for this geometry. - * @param {Color} [options.color] The color of the geometry when a per-geometry color appearance is used. - * @param {DOC_TBA} [options.pickData] DOC_TBA * * @exception {DeveloperError} options.extent is required and must have north, south, east and west attributes. * @exception {DeveloperError} options.extent.north must be in the interval [-Pi/2, Pi/2]. @@ -324,30 +319,6 @@ define([ * @type BoundingSphere */ this.boundingSphere = BoundingSphere.fromExtent3D(extent, ellipsoid, surfaceHeight); - - /** - * The 4x4 transformation matrix that transforms the geometry from model to world coordinates. - * When this is the identity matrix, the geometry is drawn in world coordinates, i.e., Earth's WGS84 coordinates. - * Local reference frames can be used by providing a different transformation matrix, like that returned - * by {@link Transforms.eastNorthUpToFixedFrame}. - * - * @type Matrix4 - * - * @see Transforms.eastNorthUpToFixedFrame - */ - this.modelMatrix = defaultValue(options.modelMatrix, Matrix4.IDENTITY.clone()); - - /** - * The color of the geometry when a per-geometry color appearance is used. - * - * @type Color - */ - this.color = options.color; - - /** - * DOC_TBA - */ - this.pickData = options.pickData; }; return ExtentGeometry; diff --git a/Source/Core/Geometry.js b/Source/Core/Geometry.js index 5ee7a66fce8c..bf45699a9891 100644 --- a/Source/Core/Geometry.js +++ b/Source/Core/Geometry.js @@ -1,12 +1,10 @@ /*global define*/ define([ './defaultValue', - './DeveloperError', - './Matrix4' + './DeveloperError' ], function( defaultValue, - DeveloperError, - Matrix4) { + DeveloperError) { "use strict"; /** @@ -32,45 +30,6 @@ define([ * DOC_TBA */ this.boundingSphere = options.boundingSphere; - - /** - * DOC_TBA - */ - this.modelMatrix = defaultValue(options.modelMatrix, Matrix4.IDENTITY.clone()); - - /** - * The color of the geometry when a per-geometry color appearance is used. - * - * @type Color - */ - this.color = options.color; - - /** - * DOC_TBA - */ - this.pickData = options.pickData; - }; - - /** - * DOC_TBA - * - * @exception {DeveloperError} geometries is required. - */ - Geometry.isPickable = function(geometries) { - if (typeof geometries === 'undefined') { - throw new DeveloperError('geometries is required.'); - } - - var pickable = false; - var length = geometries.length; - for (var i = 0; i < length; ++i) { - if (typeof geometries[i].pickData !== 'undefined') { - pickable = true; - break; - } - } - - return pickable; }; /** diff --git a/Source/Core/GeometryFilters.js b/Source/Core/GeometryFilters.js index 42e6c2595342..dda040f29f78 100644 --- a/Source/Core/GeometryFilters.js +++ b/Source/Core/GeometryFilters.js @@ -601,20 +601,22 @@ define([ * * @exception {DeveloperError} mesh is required. */ - GeometryFilters.transformToWorldCoordinates = function(mesh) { - if (typeof mesh === 'undefined') { - throw new DeveloperError('mesh is required.'); + GeometryFilters.transformToWorldCoordinates = function(instance) { + if (typeof instance === 'undefined') { + throw new DeveloperError('instance is required.'); } - if (mesh.modelMatrix.equals(Matrix4.IDENTITY)) { + var modelMatrix = instance.modelMatrix; + + if (modelMatrix.equals(Matrix4.IDENTITY)) { // Already in world coordinates return; } - var attributes = mesh.attributes; + var attributes = instance.geometry.attributes; // Transform attributes in known vertex formats - transformPoint(mesh.modelMatrix, attributes.position); + transformPoint(modelMatrix, attributes.position); if ((typeof attributes.normal !== 'undefined') || (typeof attributes.binormal !== 'undefined') || @@ -622,7 +624,7 @@ define([ var inverseTranspose = new Matrix4(); var normalMatrix = new Matrix3(); - Matrix4.inverse(mesh.modelMatrix, inverseTranspose); + Matrix4.inverse(modelMatrix, inverseTranspose); Matrix4.transpose(inverseTranspose, inverseTranspose); Matrix4.getRotation(inverseTranspose, normalMatrix); @@ -631,75 +633,78 @@ define([ transformVector(normalMatrix, attributes.tangent); } - if (typeof mesh.boundingSphere !== 'undefined') { - Matrix4.multiplyByPoint(mesh.modelMatrix, mesh.boundingSphere.center, mesh.boundingSphere.center); - mesh.boundingSphere.center = Cartesian3.fromCartesian4(mesh.boundingSphere.center); + var boundingSphere = instance.geometry.boundingSphere; + + if (typeof boundingSphere !== 'undefined') { + Matrix4.multiplyByPoint(modelMatrix, boundingSphere.center, boundingSphere.center); + boundingSphere.center = Cartesian3.fromCartesian4(boundingSphere.center); } - mesh.modelMatrix = Matrix4.IDENTITY.clone(); + instance.modelMatrix = Matrix4.IDENTITY.clone(); - return mesh; + return instance; }; - function findAttributesInAllMeshes(meshes) { - var length = meshes.length; + function findAttributesInAllGeometries(instances) { + var length = instances.length; - var attributesInAllMeshes = {}; + var attributesInAllGeometries = {}; - var attributes0 = meshes[0].attributes; + var attributes0 = instances[0].geometry.attributes; var name; for (name in attributes0) { if (attributes0.hasOwnProperty(name)) { var attribute = attributes0[name]; var numberOfComponents = attribute.values.length; - var inAllMeshes = true; + var inAllGeometries = true; - // Does this same attribute exist in all meshes? + // Does this same attribute exist in all geometries? for (var i = 1; i < length; ++i) { - var otherAttribute = meshes[i].attributes[name]; + var otherAttribute = instances[i].geometry.attributes[name]; if ((typeof otherAttribute === 'undefined') || (attribute.componentDatatype !== otherAttribute.componentDatatype) || (attribute.componentsPerAttribute !== otherAttribute.componentsPerAttribute) || (attribute.normalize !== otherAttribute.normalize)) { - inAllMeshes = false; + inAllGeometries = false; break; } numberOfComponents += otherAttribute.values.length; } - if (inAllMeshes) { - attributesInAllMeshes[name] = new GeometryAttribute({ + if (inAllGeometries) { + attributesInAllGeometries[name] = new GeometryAttribute({ componentDatatype : attribute.componentDatatype, componentsPerAttribute : attribute.componentsPerAttribute, normalize : attribute.normalize, +// TODO: or new Array() values : attribute.componentDatatype.createTypedArray(numberOfComponents) }); } } } - return attributesInAllMeshes; + return attributesInAllGeometries; } /** * DOC_TBA * - * @exception {DeveloperError} meshes is required and must have length greater than zero. - * @exception {DeveloperError} All meshes must have the same modelMatrix. + * @exception {DeveloperError} instances is required and must have length greater than zero. + * @exception {DeveloperError} All instances must have the same modelMatrix. */ - GeometryFilters.combine = function(meshes) { - if ((typeof meshes === 'undefined') || (meshes.length < 1)) { - throw new DeveloperError('meshes is required and must have length greater than zero.'); + GeometryFilters.combine = function(instances) { + if ((typeof instances === 'undefined') || (instances.length < 1)) { + throw new DeveloperError('instances is required and must have length greater than zero.'); } - var length = meshes.length; + var length = instances.length; if (length === 1) { - return meshes[0]; + return instances[0].geometry; } var name; @@ -707,15 +712,15 @@ define([ var j; var k; - var m = meshes[0].modelMatrix; + var m = instances[0].modelMatrix; for (i = 1; i < length; ++i) { - if (!Matrix4.equals(meshes[i].modelMatrix, m)) { - throw new DeveloperError('All meshes must have the same modelMatrix.'); + if (!Matrix4.equals(instances[i].modelMatrix, m)) { + throw new DeveloperError('All instances must have the same modelMatrix.'); } } - // Find subset of attributes in all meshes - var attributes = findAttributesInAllMeshes(meshes); + // Find subset of attributes in all geometries + var attributes = findAttributesInAllGeometries(instances); var values; var sourceValues; var sourceValuesLength; @@ -730,7 +735,7 @@ define([ k = 0; for (i = 0; i < length; ++i) { - sourceValues = meshes[i].attributes[name].values; + sourceValues = instances[i].geometry.attributes[name].values; sourceValuesLength = sourceValues.length; for (j = 0; j < sourceValuesLength; ++j) { @@ -740,7 +745,8 @@ define([ } } - // PERFORMANCE_IDEA: Could combine with fitToUnsignedShortIndices, but it would start to get ugly. + // PERFORMANCE_IDEA: Could combine with fitToUnsignedShortIndices, but it would start to get ugly + // and it is not needed when OES_element_index_uint is supported. // Combine index lists @@ -751,7 +757,7 @@ define([ var indices; for (i = 0; i < length; ++i) { - indexLists = meshes[i].indexLists; + indexLists = instances[i].geometry.indexLists; indexListsLength = indexLists.length; for (j = 0; j < indexListsLength; ++j) { @@ -770,6 +776,7 @@ define([ if (numberOfIndices.hasOwnProperty(name)) { var num = numberOfIndices[name]; +// TODO: or new Array() if (num < 60 * 1024) { values = new Uint16Array(num); } else { @@ -792,7 +799,7 @@ define([ var offset = 0; for (i = 0; i < length; ++i) { - indexLists = meshes[i].indexLists; + indexLists = instances[i].geometry.indexLists; indexListsLength = indexLists.length; for (j = 0; j < indexListsLength; ++j) { @@ -809,7 +816,7 @@ define([ indexListsByPrimitiveType[indices.primitiveType].currentOffset = n; } - var attrs = meshes[i].attributes; + var attrs = instances[i].geometry.attributes; for (name in attrs) { if (attrs.hasOwnProperty(name)) { offset += attrs[name].values.length / attrs[name].componentsPerAttribute; @@ -818,11 +825,11 @@ define([ } } - // Create bounding sphere that includes all meshes + // Create bounding sphere that includes all instances var boundingSphere; for (i = 0; i < length; ++i) { - var bs = meshes[i].boundingSphere; + var bs = instances[i].geometry.boundingSphere; if (typeof bs === 'undefined') { // If any meshes have an undefined bounding sphere, then so does the combined mesh boundingSphere = undefined; @@ -843,6 +850,11 @@ define([ }); }; + var normal = new Cartesian3(); + var v0 = new Cartesian3(); + var v1 = new Cartesian3(); + var v2 = new Cartesian3(); + /** * Computes the normals of all vertices in a mesh based on the normals of triangles that include the vertex. * This assumes a counter-clockwise vertex winding order. @@ -859,10 +871,6 @@ define([ * mesh = GeometryFilters.computeNormal(mesh); * */ - var normal = new Cartesian3(); - var v0 = new Cartesian3(); - var v1 = new Cartesian3(); - var v2 = new Cartesian3(); GeometryFilters.computeNormal = function(mesh) { if (typeof mesh === 'undefined') { throw new DeveloperError('mesh is required.'); @@ -990,6 +998,10 @@ define([ return mesh; }; + var normalScratch = new Cartesian3(); + var normalScale = new Cartesian3(); + var tScratch = new Cartesian3(); + /** * Computes the tangent and binormal of all vertices in a geometry * This assumes a counter-clockwise vertex winding order. @@ -1013,9 +1025,6 @@ define([ * @example * geometry = GeometryFilters.computeTangentAndBinormal(geometry); */ - var normalScratch = new Cartesian3(); - var normalScale = new Cartesian3(); - var tScratch = new Cartesian3(); GeometryFilters.computeTangentAndBinormal = function(geometry) { if (typeof geometry === 'undefined') { throw new DeveloperError('geometry is required.'); diff --git a/Source/Core/GeometryInstance.js b/Source/Core/GeometryInstance.js new file mode 100644 index 000000000000..0f6eecc8efb6 --- /dev/null +++ b/Source/Core/GeometryInstance.js @@ -0,0 +1,53 @@ +/*global define*/ +define([ + './defaultValue', + './Matrix4' + ], function( + defaultValue, + Matrix4) { + "use strict"; + + /** + * DOC_TBA + * + * @alias GeometryInstance + * @constructor + * + * @param {Geometry} [options.geometry] The geometry to instance. + * @param {Matrix4} [options.modelMatrix] The model matrix for this ellipsoid. + * @param {Color} [options.color] The color of the geometry when a per-geometry color appearance is used. + * @param {Object} [options.pickData] DOC_TBA + */ + var GeometryInstance = function(options) { + options = defaultValue(options, defaultValue.EMPTY_OBJECT); + + /** + * DOC_TBA + */ + this.geometry = options.geometry; + + /** + * The 4x4 transformation matrix that transforms the geometry from model to world coordinates. + * When this is the identity matrix, the geometry is drawn in world coordinates, i.e., Earth's WGS84 coordinates. + * Local reference frames can be used by providing a different transformation matrix, like that returned + * by {@link Transforms.eastNorthUpToFixedFrame}. + * + * @type Matrix4 + */ + this.modelMatrix = defaultValue(options.modelMatrix, Matrix4.IDENTITY.clone()); + + /** + * The color of the geometry when a per-geometry color appearance is used. + * + * @type Color + */ + this.color = options.color; + + /** + * DOC_TBA + */ + this.pickData = options.pickData; + }; + + return GeometryInstance; +}); diff --git a/Source/Core/PolygonGeometry.js b/Source/Core/PolygonGeometry.js index 5bb3132d6598..e8b3ccab8b7c 100644 --- a/Source/Core/PolygonGeometry.js +++ b/Source/Core/PolygonGeometry.js @@ -11,11 +11,11 @@ define([ './Ellipsoid', './EllipsoidTangentPlane', './GeometryAttribute', + './GeometryInstance', './GeometryFilters', './Intersect', './Math', './Matrix3', - './Matrix4', './PolygonPipeline', './Quaternion', './Queue', @@ -33,11 +33,11 @@ define([ Ellipsoid, EllipsoidTangentPlane, GeometryAttribute, + GeometryInstance, GeometryFilters, Intersect, CesiumMath, Matrix3, - Matrix4, PolygonPipeline, Quaternion, Queue, @@ -110,7 +110,9 @@ define([ if ((minX < 0) && (BoundingSphere.intersect(boundingSphere, Cartesian4.UNIT_Y) === Intersect.INTERSECTING)) { indices = PolygonPipeline.wrapLongitude(cleanedPositions, indices); } - return PolygonPipeline.computeSubdivision(cleanedPositions, indices, granularity); + return new GeometryInstance({ + geometry : PolygonPipeline.computeSubdivision(cleanedPositions, indices, granularity) + }); } var scratchBoundingRectangle = new BoundingRectangle(); @@ -139,9 +141,6 @@ define([ * @param {Number} [options.stRotation=0.0] The rotation of the texture coordiantes, in radians. A positive rotation is counter-clockwise. * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid to be used as a reference. * @param {Number} [options.granularity=CesiumMath.toRadians(1.0)] The distance, in radians, between each latitude and longitude. Determines the number of positions in the buffer. - * @param {Matrix4} [options.modelMatrix] The model matrix for this geometry. - * @param {Color} [options.color] The color of the geometry when a per-geometry color appearance is used. - * @param {DOC_TBA} [options.pickData] DOC_TBA * * @exception {DeveloperError} At least three positions are required. * @exception {DeveloperError} positions or polygonHierarchy must be supplied. @@ -426,28 +425,6 @@ define([ * @type BoundingSphere */ this.boundingSphere = boundingSphere; - - /** - * The 4x4 transformation matrix that transforms the geometry from model to world coordinates. - * When this is the identity matrix, the geometry is drawn in world coordinates, i.e., Earth's WGS84 coordinates. - * Local reference frames can be used by providing a different transformation matrix, like that returned - * by {@link Transforms.eastNorthUpToFixedFrame}. - * - * @type Matrix4 - */ - this.modelMatrix = defaultValue(options.modelMatrix, Matrix4.IDENTITY.clone()); - - /** - * The color of the geometry when a per-geometry color appearance is used. - * - * @type Color - */ - this.color = options.color; - - /** - * DOC_TBA - */ - this.pickData = options.pickData; }; return PolygonGeometry; diff --git a/Source/Core/PolygonPipeline.js b/Source/Core/PolygonPipeline.js index ef99c8f45110..2533c7936e07 100644 --- a/Source/Core/PolygonPipeline.js +++ b/Source/Core/PolygonPipeline.js @@ -4,6 +4,9 @@ define([ './Math', './Cartesian2', './Cartesian3', + './Geometry', + './GeometryAttribute', + './GeometryIndices', './Ellipsoid', './EllipsoidTangentPlane', './defaultValue', @@ -17,6 +20,9 @@ define([ CesiumMath, Cartesian2, Cartesian3, + Geometry, + GeometryAttribute, + GeometryIndices, Ellipsoid, EllipsoidTangentPlane, defaultValue, @@ -823,20 +829,20 @@ define([ flattenedPositions[q++] = item.z; } - return { + return new Geometry({ attributes : { - position : { + position : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 3, values : flattenedPositions - } + }) }, - indexLists : [{ + indexLists : [new GeometryIndices({ primitiveType : PrimitiveType.TRIANGLES, values : subdividedIndices - }] - }; + })] + }); }, /** diff --git a/Source/Core/WallGeometry.js b/Source/Core/WallGeometry.js index cb3360cef696..7231690a11ed 100644 --- a/Source/Core/WallGeometry.js +++ b/Source/Core/WallGeometry.js @@ -10,7 +10,6 @@ define([ './EllipsoidTangentPlane', './GeometryAttribute', './GeometryIndices', - './Matrix4', './PolylinePipeline', './PolygonPipeline', './PrimitiveType', @@ -27,7 +26,6 @@ define([ EllipsoidTangentPlane, GeometryAttribute, GeometryIndices, - Matrix4, PolylinePipeline, PolygonPipeline, PrimitiveType, @@ -58,28 +56,23 @@ define([ * this height. Otherwise, its treated as 'ground' (the WGS84 ellipsoid height 0). * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid for coordinate manipulation * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed. - * @param {Matrix4} [options.modelMatrix] The model matrix for this geometry. - * @param {Color} [options.color] The color of the geometry when a per-geometry color appearance is used. - * @param {DOC_TBA} [options.pickData] DOC_TBA * * @exception {DeveloperError} positions is required. * @exception {DeveloperError} positions and terrain points must have the same length. * * @example + * var positions = [ + * Cesium.Cartographic.fromDegrees(19.0, 47.0, 10000.0), + * Cesium.Cartographic.fromDegrees(19.0, 48.0, 10000.0), + * Cesium.Cartographic.fromDegrees(20.0, 48.0, 10000.0), + * Cesium.Cartographic.fromDegrees(20.0, 47.0, 10000.0), + * Cesium.Cartographic.fromDegrees(19.0, 47.0, 10000.0) + * ]; * - * var positions = [ - * Cesium.Cartographic.fromDegrees(19.0, 47.0, 10000.0), - * Cesium.Cartographic.fromDegrees(19.0, 48.0, 10000.0), - * Cesium.Cartographic.fromDegrees(20.0, 48.0, 10000.0), - * Cesium.Cartographic.fromDegrees(20.0, 47.0, 10000.0), - * Cesium.Cartographic.fromDegrees(19.0, 47.0, 10000.0) - * ]; - * - * // create a wall that spans from ground level to 10000 meters - * var wall = new Cesium.WallGeometry({ - * positions : ellipsoid.cartographicArrayToCartesianArray(positions) - * }); - * + * // create a wall that spans from ground level to 10000 meters + * var wall = new Cesium.WallGeometry({ + * positions : ellipsoid.cartographicArrayToCartesianArray(positions) + * }); */ var WallGeometry = function(options) { options = defaultValue(options, defaultValue.EMPTY_OBJECT); @@ -306,28 +299,6 @@ define([ * @type BoundingSphere */ this.boundingSphere = new BoundingSphere.fromVertices(positions); - - /** - * The 4x4 transformation matrix that transforms the geometry from model to world coordinates. - * When this is the identity matrix, the geometry is drawn in world coordinates, i.e., Earth's WGS84 coordinates. - * Local reference frames can be used by providing a different transformation matrix, like that returned - * by {@link Transforms.eastNorthUpToFixedFrame}. - * - * @type Matrix4 - */ - this.modelMatrix = defaultValue(options.modelMatrix, Matrix4.IDENTITY.clone()); - - /** - * The color of the geometry when a per-geometry color appearance is used. - * - * @type Color - */ - this.color = options.color; - - /** - * DOC_TBA - */ - this.pickData = options.pickData; }; return WallGeometry; diff --git a/Source/Scene/Polygon.js b/Source/Scene/Polygon.js index a0734dced0ae..66fc76128730 100644 --- a/Source/Scene/Polygon.js +++ b/Source/Scene/Polygon.js @@ -14,6 +14,7 @@ define([ '../Core/Cartesian4', '../Core/ComponentDatatype', '../Core/GeometryFilters', + '../Core/GeometryInstance', '../Core/PrimitiveType', '../Core/EllipsoidTangentPlane', '../Core/PolygonPipeline', @@ -48,6 +49,7 @@ define([ Cartesian4, ComponentDatatype, GeometryFilters, + GeometryInstance, PrimitiveType, EllipsoidTangentPlane, PolygonPipeline, @@ -518,7 +520,10 @@ define([ var boundary = outerPositions || cleanedPositions; var boundingRectangle = computeBoundingRectangle(tangentPlane, boundary, angle, createMeshFromPositionsBoundingRectangle); mesh = appendTextureCoordinates(tangentPlane, boundingRectangle, mesh, angle); - return mesh; + + return new GeometryInstance({ + geometry : mesh + }); } function createMeshes(polygon) { diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index f985c72a043a..866c4b4d73ad 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -46,7 +46,7 @@ define([ /** * DOC_TBA */ - this.geometries = options.geometries; + this.geometryInstances = options.geometryInstances; /** * DOC_TBA @@ -78,24 +78,25 @@ define([ this._commandLists = new CommandLists(); }; - function hasPerGeometryColor(geometries) { - var perGeometryColor = false; - var length = geometries.length; + function hasPerInstanceColor(instances) { + var perInstanceColor = false; + var length = instances.length; for (var i = 0; i < length; ++i) { - if (typeof geometries[i].color !== 'undefined') { - perGeometryColor = true; + if (typeof instances[i].color !== 'undefined') { + perInstanceColor = true; break; } } - return perGeometryColor; + return perInstanceColor; } - function addColorAttribute(primitive, geometries, context) { - var length = geometries.length; + function addColorAttribute(primitive, instances, context) { + var length = instances.length; for (var i = 0; i < length; ++i) { - var geometry = geometries[i]; + var instance = instances[i]; + var geometry = instance.geometry; var attributes = geometry.attributes; var positionAttr = attributes.position; var numberOfComponents = 4 * (positionAttr.values.length / positionAttr.componentsPerAttribute); @@ -107,7 +108,7 @@ define([ values : new Uint8Array(numberOfComponents) }); - var color = geometry.color; + var color = instance.color; if (typeof color !== 'undefined') { var red = Color.floatToByte(color.red); @@ -126,11 +127,11 @@ define([ } } - function isPickable(geometries) { + function isPickable(instances) { var pickable = false; - var length = geometries.length; + var length = instances.length; for (var i = 0; i < length; ++i) { - if (typeof geometries[i].pickData !== 'undefined') { + if (typeof instances[i].pickData !== 'undefined') { pickable = true; break; } @@ -139,11 +140,12 @@ define([ return pickable; } - function addPickColorAttribute(primitive, geometries, context) { - var length = geometries.length; + function addPickColorAttribute(primitive, instances, context) { + var length = instances.length; for (var i = 0; i < length; ++i) { - var geometry = geometries[i]; + var instance = instances[i]; + var geometry = instance.geometry; var attributes = geometry.attributes; var positionAttr = attributes.position; var numberOfComponents = 4 * (positionAttr.values.length / positionAttr.componentsPerAttribute); @@ -155,10 +157,10 @@ define([ values : new Uint8Array(numberOfComponents) }); - if (typeof geometry.pickData !== 'undefined') { + if (typeof instance.pickData !== 'undefined') { var pickId = context.createPickId({ primitive : primitive, - pickData : geometry.pickData + pickData : instance.pickData }); primitive._pickIds.push(pickId); @@ -179,10 +181,10 @@ define([ } } - function addDefaultAttributes(geometries) { - var length = geometries.length; + function addDefaultAttributes(instances) { + var length = instances.length; for (var i = 0; i < length; ++i) { - var geometry = geometries[i]; + var geometry = instances[i].geometry; var attributes = geometry.attributes; var positionAttr = attributes.position; var positionLength = positionAttr.values.length / positionAttr.componentsPerAttribute; @@ -256,16 +258,16 @@ define([ } } - function transformToWorldCoordinates(primitive, geometries) { + function transformToWorldCoordinates(primitive, instances) { var toWorld = primitive._transformToWorldCoordinates; - var length = geometries.length; + var length = instances.length; var i; if (!toWorld && (length > 1)) { - var modelMatrix = Matrix4.clone(geometries[0].modelMatrix); + var modelMatrix = instances[0].modelMatrix; for (i = 1; i < length; ++i) { - if (!Matrix4.equals(modelMatrix, geometries[i])) { + if (!Matrix4.equals(modelMatrix, instances[i].modelMatrix)) { toWorld = true; break; } @@ -274,34 +276,37 @@ define([ if (toWorld) { for (i = 0; i < length; ++i) { - GeometryFilters.transformToWorldCoordinates(geometries[i]); + GeometryFilters.transformToWorldCoordinates(instances[i]); } } else { // Leave geometry in local coordinate system; auto update model-matrix. - Matrix4.clone(geometries[0].modelMatrix, primitive.modelMatrix); + Matrix4.clone(instances[0].modelMatrix, primitive.modelMatrix); } } - function geometryPipeline(primitive, geometries, context) { + function geometryPipeline(primitive, instances, context) { + +// TODO: copy instances first since we don't want to modify what they instance. + // Add color attribute if any geometries have per-geometry color - if (hasPerGeometryColor(geometries)) { - addColorAttribute(primitive, geometries, context); + if (hasPerInstanceColor(instances)) { + addColorAttribute(primitive, instances, context); } // Add pickColor attribute if any geometries are pickable - if (isPickable(geometries)) { - addPickColorAttribute(primitive, geometries, context); + if (isPickable(instances)) { + addPickColorAttribute(primitive, instances, context); } // Add default values for any undefined attributes - addDefaultAttributes(geometries); + addDefaultAttributes(instances); // Unify to world coordinates before combining. If there is only one geometry or all // geometries are in the same (non-world) coordinate system, only combine if the user requested it. - transformToWorldCoordinates(primitive, geometries); + transformToWorldCoordinates(primitive, instances); // Combine into single geometry for better rendering performance. - var geometry = GeometryFilters.combine(geometries); + var geometry = GeometryFilters.combine(instances); // Split position for GPU RTE GeometryFilters.encodeAttribute(geometry, 'position', 'positionHigh', 'positionLow'); @@ -321,7 +326,7 @@ define([ Primitive.prototype.update = function(context, frameState, commandList) { if (!this.show || (frameState.mode !== SceneMode.SCENE3D) || - ((typeof this.geometries === 'undefined') && (this._va.length === 0)) || + ((typeof this.geometryInstances === 'undefined') && (this._va.length === 0)) || (typeof this.appearance === 'undefined')) { // TODO: support Columbus view and 2D return; @@ -333,24 +338,24 @@ define([ var i; if (this._va.length === 0) { - var geometries = (this.geometries instanceof Array) ? this.geometries : [this.geometries]; - var finalGeometries = geometryPipeline(this, geometries, context); + var instances = (this.geometryInstances instanceof Array) ? this.geometryInstances : [this.geometryInstances]; + var geometries = geometryPipeline(this, instances, context); - length = finalGeometries.length; + length = geometries.length; if (this._vertexCacheOptimize) { // Optimize for vertex shader caches for (i = 0; i < length; ++i) { - GeometryFilters.reorderForPostVertexCache(finalGeometries[i]); - GeometryFilters.reorderForPreVertexCache(finalGeometries[i]); + GeometryFilters.reorderForPostVertexCache(geometries[i]); + GeometryFilters.reorderForPreVertexCache(geometries[i]); } } - var attributeIndices = GeometryFilters.createAttributeIndices(finalGeometries[0]); + var attributeIndices = GeometryFilters.createAttributeIndices(geometries[0]); var va = []; for (i = 0; i < length; ++i) { va.push(context.createVertexArrayFromMesh({ - mesh : finalGeometries[i], + mesh : geometries[i], attributeIndices : attributeIndices, bufferUsage : BufferUsage.STATIC_DRAW, vertexLayout : VertexLayout.INTERLEAVED @@ -367,7 +372,7 @@ define([ var rs = context.createRenderState(appearance.renderState); var pickRS; - if (isPickable(geometries)) { + if (isPickable(instances)) { this._pickSP = context.getShaderCache().replaceShaderProgram(this._pickSP, vs, createPickFragmentShaderSource(fs, 'varying'), attributeIndices); pickRS = rs; } else { @@ -387,7 +392,7 @@ define([ var uniforms = (typeof appearance.material !== 'undefined') ? appearance.material._uniforms : undefined; for (i = 0; i < length; ++i) { - var geometry = finalGeometries[i]; + var geometry = geometries[i]; var command = new DrawCommand(); // TODO: this assumes indices in the geometries - and only one set @@ -410,7 +415,7 @@ define([ } if (this._releaseGeometries) { - this.geometries = undefined; + this.geometryInstances = undefined; } } diff --git a/Specs/Core/BoxGeometrySpec.js b/Specs/Core/BoxGeometrySpec.js index 06d9d8a35d57..bdb28d33a441 100644 --- a/Specs/Core/BoxGeometrySpec.js +++ b/Specs/Core/BoxGeometrySpec.js @@ -49,7 +49,5 @@ defineSuite([ expect(m.boundingSphere.center).toEqual(Cartesian3.ZERO); expect(m.boundingSphere.radius).toEqual(maximumCorner.magnitude() * 0.5); - - expect(m.modelMatrix).toEqual(Matrix4.IDENTITY); }); }); \ No newline at end of file diff --git a/Specs/Core/EllipsoidGeometrySpec.js b/Specs/Core/EllipsoidGeometrySpec.js index 65f9035165c8..cca9cf9da5ae 100644 --- a/Specs/Core/EllipsoidGeometrySpec.js +++ b/Specs/Core/EllipsoidGeometrySpec.js @@ -73,6 +73,4 @@ defineSuite([ expect(binormal).toEqualEpsilon(Cartesian3.cross(normal, tangent), CesiumMath.EPSILON10); } }); - - }); \ No newline at end of file diff --git a/Specs/Core/GeometryFiltersSpec.js b/Specs/Core/GeometryFiltersSpec.js index 8c4137a53cee..6efaab9037a6 100644 --- a/Specs/Core/GeometryFiltersSpec.js +++ b/Specs/Core/GeometryFiltersSpec.js @@ -12,6 +12,7 @@ defineSuite([ 'Core/Geometry', 'Core/GeometryAttribute', 'Core/GeometryIndices', + 'Core/GeometryInstance', 'Core/VertexFormat', 'Core/Math' ], function( @@ -27,6 +28,7 @@ defineSuite([ Geometry, GeometryAttribute, GeometryIndices, + GeometryInstance, VertexFormat, CesiumMath) { "use strict"; @@ -506,73 +508,79 @@ defineSuite([ }); it('GeometryFilters.combine combines one mesh', function() { - var mesh = new Geometry({ - attributes : new GeometryAttribute({ - position : { - componentDatatype : ComponentDatatype.FLOAT, - componentsPerAttribute : 3, - values : [0.0, 0.0, 0.0] - } - }) + var instance = new GeometryInstance({ + geometry : new Geometry({ + attributes : new GeometryAttribute({ + position : { + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : [0.0, 0.0, 0.0] + } + }) + }), }); - var combinedMesh = GeometryFilters.combine([mesh]); - expect(combinedMesh).toBe(mesh); + var combined = GeometryFilters.combine([instance]); + expect(combined).toBe(instance.geometry); }); it('GeometryFilters.combine combines several meshes', function() { - var mesh = new Geometry({ - attributes : { - position : new GeometryAttribute({ - componentDatatype : ComponentDatatype.FLOAT, - componentsPerAttribute : 3, - values : [ - 0.0, 0.0, 0.0, - 1.0, 1.0, 1.0, - 2.0, 2.0, 2.0 - ] - }), - normal : new GeometryAttribute({ - componentDatatype : ComponentDatatype.FLOAT, - componentsPerAttribute : 3, - values : [ - 0.0, 0.0, 0.0, - 1.0, 1.0, 1.0, - 2.0, 2.0, 2.0 - ] - }) - }, - indexLists : [new GeometryIndices({ - primitiveType : PrimitiveType.TRIANGLES, - values : [0, 1, 2] - }), new GeometryIndices({ - primitiveType : PrimitiveType.LINES, - values : [1, 2] - })] + var instance = new GeometryInstance({ + geometry : new Geometry({ + attributes : { + position : new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : [ + 0.0, 0.0, 0.0, + 1.0, 1.0, 1.0, + 2.0, 2.0, 2.0 + ] + }), + normal : new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : [ + 0.0, 0.0, 0.0, + 1.0, 1.0, 1.0, + 2.0, 2.0, 2.0 + ] + }) + }, + indexLists : [new GeometryIndices({ + primitiveType : PrimitiveType.TRIANGLES, + values : [0, 1, 2] + }), new GeometryIndices({ + primitiveType : PrimitiveType.LINES, + values : [1, 2] + })] + }) }); - var anotherMesh = new Geometry({ - attributes : { - position : new GeometryAttribute({ - componentDatatype : ComponentDatatype.FLOAT, - componentsPerAttribute : 3, - values : [ - 3.0, 3.0, 3.0, - 4.0, 4.0, 4.0, - 5.0, 5.0, 5.0 - ] - }) - }, - indexLists : [new GeometryIndices({ - primitiveType : PrimitiveType.TRIANGLES, - values : [0, 1, 2] - }), new GeometryIndices({ - primitiveType : PrimitiveType.POINTS, - values : [0, 1, 2] - })] + var anotherInstance = new GeometryInstance({ + geometry : new Geometry({ + attributes : { + position : new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : [ + 3.0, 3.0, 3.0, + 4.0, 4.0, 4.0, + 5.0, 5.0, 5.0 + ] + }) + }, + indexLists : [new GeometryIndices({ + primitiveType : PrimitiveType.TRIANGLES, + values : [0, 1, 2] + }), new GeometryIndices({ + primitiveType : PrimitiveType.POINTS, + values : [0, 1, 2] + })] + }) }); - var combinedMesh = GeometryFilters.combine([mesh, anotherMesh]); - expect(combinedMesh).toEqual(new Geometry({ + var combined = GeometryFilters.combine([instance, anotherInstance]); + expect(combined).toEqual(new Geometry({ attributes : { position : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, @@ -600,13 +608,13 @@ defineSuite([ })); }); - it('GeometryFilters.combine throws with meshes', function() { + it('GeometryFilters.combine throws with instances', function() { expect(function() { GeometryFilters.combine(); }).toThrow(); }); - it('GeometryFilters.combine throws when meshes.length is zero', function() { + it('GeometryFilters.combine throws when instances.length is zero', function() { expect(function() { GeometryFilters.combine([]); }).toThrow(); diff --git a/Specs/Core/PolygonGeometrySpec.js b/Specs/Core/PolygonGeometrySpec.js index ee53332a04be..d14eb652411a 100644 --- a/Specs/Core/PolygonGeometrySpec.js +++ b/Specs/Core/PolygonGeometrySpec.js @@ -118,28 +118,28 @@ defineSuite([ it('creates a polygon from hierarchy', function() { var hierarchy = { + positions : Ellipsoid.WGS84.cartographicArrayToCartesianArray([ + Cartographic.fromDegrees(-124.0, 35.0, 0.0), + Cartographic.fromDegrees(-110.0, 35.0, 0.0), + Cartographic.fromDegrees(-110.0, 40.0, 0.0), + Cartographic.fromDegrees(-124.0, 40.0, 0.0) + ]), + holes : [{ positions : Ellipsoid.WGS84.cartographicArrayToCartesianArray([ - Cartographic.fromDegrees(-124.0, 35.0, 0.0), - Cartographic.fromDegrees(-110.0, 35.0, 0.0), - Cartographic.fromDegrees(-110.0, 40.0, 0.0), - Cartographic.fromDegrees(-124.0, 40.0, 0.0) + Cartographic.fromDegrees(-122.0, 36.0, 0.0), + Cartographic.fromDegrees(-122.0, 39.0, 0.0), + Cartographic.fromDegrees(-112.0, 39.0, 0.0), + Cartographic.fromDegrees(-112.0, 36.0, 0.0) ]), holes : [{ positions : Ellipsoid.WGS84.cartographicArrayToCartesianArray([ - Cartographic.fromDegrees(-122.0, 36.0, 0.0), - Cartographic.fromDegrees(-122.0, 39.0, 0.0), - Cartographic.fromDegrees(-112.0, 39.0, 0.0), - Cartographic.fromDegrees(-112.0, 36.0, 0.0) - ]), - holes : [{ - positions : Ellipsoid.WGS84.cartographicArrayToCartesianArray([ - Cartographic.fromDegrees(-120.0, 36.5, 0.0), - Cartographic.fromDegrees(-114.0, 36.5, 0.0), - Cartographic.fromDegrees(-114.0, 38.5, 0.0), - Cartographic.fromDegrees(-120.0, 38.5, 0.0) - ]) - }] + Cartographic.fromDegrees(-120.0, 36.5, 0.0), + Cartographic.fromDegrees(-114.0, 36.5, 0.0), + Cartographic.fromDegrees(-114.0, 38.5, 0.0), + Cartographic.fromDegrees(-120.0, 38.5, 0.0) + ]) }] + }] }; var p = new PolygonGeometry({ From 310cf0ae41f2f6a3800377df8989fa154cdf8d38 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Tue, 4 Jun 2013 15:03:39 -0400 Subject: [PATCH 139/306] Finish instancing --- Apps/Sandcastle/gallery/Wall.html | 38 +++++++++++-------- Source/Core/BoxGeometry.js | 7 ++++ Source/Core/CircleGeometry.js | 7 ++++ Source/Core/EllipseGeometry.js | 7 ++++ Source/Core/EllipsoidGeometry.js | 7 ++++ Source/Core/ExtentGeometry.js | 7 ++++ Source/Core/Geometry.js | 37 +++++++++++++++++- Source/Core/GeometryAttribute.js | 25 ++++++++++++ Source/Core/GeometryFilters.js | 63 +++++++++++++------------------ Source/Core/GeometryIndices.js | 22 +++++++++++ Source/Core/GeometryInstance.js | 18 ++++++++- Source/Core/Matrix4.js | 46 +++++++++++----------- Source/Core/PolygonGeometry.js | 7 ++++ Source/Core/WallGeometry.js | 7 ++++ Source/Scene/Primitive.js | 22 ++++++----- 15 files changed, 233 insertions(+), 87 deletions(-) diff --git a/Apps/Sandcastle/gallery/Wall.html b/Apps/Sandcastle/gallery/Wall.html index 12e5c01af6ed..a88bfd18cbeb 100644 --- a/Apps/Sandcastle/gallery/Wall.html +++ b/Apps/Sandcastle/gallery/Wall.html @@ -66,28 +66,32 @@ ]; // create a wall that spans from ground level to 10000 meters - var wall1 = new Cesium.WallGeometry({ - positions : ellipsoid.cartographicArrayToCartesianArray(positions), - pickData : 'wall1' + var wall1 = new Cesium.GeometryInstance({ + geometry : new Cesium.WallGeometry({ + positions : ellipsoid.cartographicArrayToCartesianArray(positions) + }), + pickData : 'wall1' }); var primitive = new Cesium.Primitive({ - geometries : wall1, + geometryInstances : wall1, appearance : appearance }); primitives.add(primitive); // create a wall with the same coordinates, but from 15000 - 25000 meters - var wall2 = new Cesium.WallGeometry({ - positions : ellipsoid.cartographicArrayToCartesianArray(positions), - bottom : 15000, - top : 25000, - pickData : 'wall2' + var wall2 = new Cesium.GeometryInstance({ + geometry : new Cesium.WallGeometry({ + positions : ellipsoid.cartographicArrayToCartesianArray(positions), + bottom : 15000, + top : 25000 + }), + pickData : 'wall2' }); - + primitive = new Cesium.Primitive({ - geometries : wall2, + geometryInstances : wall2, appearance : appearance }); @@ -109,14 +113,16 @@ } Cesium.when(Cesium.sampleTerrain(terrainProvider, 11, t), function(terrain) { - var wall3 = new Cesium.WallGeometry({ - positions : ellipsoid.cartographicArrayToCartesianArray(positions), - terrain : terrain, - pickData : 'wall3' + var wall3 = new Cesium.GeometryInstance({ + geometry : new Cesium.WallGeometry({ + positions : ellipsoid.cartographicArrayToCartesianArray(positions), + terrain : terrain, + }), + pickData : 'wall3' }); var p = new Cesium.Primitive({ - geometries : wall3, + geometryInstances : wall3, appearance : appearance }); diff --git a/Source/Core/BoxGeometry.js b/Source/Core/BoxGeometry.js index 2abb516fbfd8..43f464d78b4a 100644 --- a/Source/Core/BoxGeometry.js +++ b/Source/Core/BoxGeometry.js @@ -6,6 +6,7 @@ define([ './PrimitiveType', './defaultValue', './BoundingSphere', + './Geometry', './GeometryAttribute', './GeometryIndices', './VertexFormat' @@ -16,6 +17,7 @@ define([ PrimitiveType, defaultValue, BoundingSphere, + Geometry, GeometryAttribute, GeometryIndices, VertexFormat) { @@ -382,5 +384,10 @@ define([ this.boundingSphere = new BoundingSphere(new Cartesian3(), max.subtract(min).magnitude() * 0.5); }; + /** + * DOC_TBA + */ + BoxGeometry.prototype.clone = Geometry.prototype.clone; + return BoxGeometry; }); \ No newline at end of file diff --git a/Source/Core/CircleGeometry.js b/Source/Core/CircleGeometry.js index fae6335ce145..aa7b7481030a 100644 --- a/Source/Core/CircleGeometry.js +++ b/Source/Core/CircleGeometry.js @@ -3,11 +3,13 @@ define([ './clone', './defaultValue', './DeveloperError', + './Geometry', './EllipseGeometry' ], function( clone, defaultValue, DeveloperError, + Geometry, EllipseGeometry) { "use strict"; @@ -78,5 +80,10 @@ define([ this.boundingSphere = ellipseGeometry.boundingSphere; }; + /** + * DOC_TBA + */ + CircleGeometry.prototype.clone = Geometry.prototype.clone; + return CircleGeometry; }); \ No newline at end of file diff --git a/Source/Core/EllipseGeometry.js b/Source/Core/EllipseGeometry.js index 3fc22c45c88a..d1ab933226db 100644 --- a/Source/Core/EllipseGeometry.js +++ b/Source/Core/EllipseGeometry.js @@ -6,6 +6,7 @@ define([ './ComponentDatatype', './DeveloperError', './Ellipsoid', + './Geometry', './GeometryAttribute', './GeometryIndices', './Math', @@ -20,6 +21,7 @@ define([ ComponentDatatype, DeveloperError, Ellipsoid, + Geometry, GeometryAttribute, GeometryIndices, CesiumMath, @@ -449,5 +451,10 @@ define([ this.boundingSphere = new BoundingSphere(center, semiMajorAxis); }; + /** + * DOC_TBA + */ + EllipseGeometry.prototype.clone = Geometry.prototype.clone; + return EllipseGeometry; }); \ No newline at end of file diff --git a/Source/Core/EllipsoidGeometry.js b/Source/Core/EllipsoidGeometry.js index e6324d935e49..f7d27d46c87d 100644 --- a/Source/Core/EllipsoidGeometry.js +++ b/Source/Core/EllipsoidGeometry.js @@ -8,6 +8,7 @@ define([ './ComponentDatatype', './PrimitiveType', './BoundingSphere', + './Geometry', './GeometryAttribute', './GeometryIndices', './VertexFormat' @@ -20,6 +21,7 @@ define([ ComponentDatatype, PrimitiveType, BoundingSphere, + Geometry, GeometryAttribute, GeometryIndices, VertexFormat) { @@ -333,5 +335,10 @@ define([ this.boundingSphere = BoundingSphere.fromEllipsoid(ellipsoid); }; + /** + * DOC_TBA + */ + EllipsoidGeometry.prototype.clone = Geometry.prototype.clone; + return EllipsoidGeometry; }); \ No newline at end of file diff --git a/Source/Core/ExtentGeometry.js b/Source/Core/ExtentGeometry.js index daa309d15266..926ef5c81d19 100644 --- a/Source/Core/ExtentGeometry.js +++ b/Source/Core/ExtentGeometry.js @@ -10,6 +10,7 @@ define([ './Ellipsoid', './Extent', './GeographicProjection', + './Geometry', './GeometryAttribute', './GeometryIndices', './Math', @@ -27,6 +28,7 @@ define([ Ellipsoid, Extent, GeographicProjection, + Geometry, GeometryAttribute, GeometryIndices, CesiumMath, @@ -321,5 +323,10 @@ define([ this.boundingSphere = BoundingSphere.fromExtent3D(extent, ellipsoid, surfaceHeight); }; + /** + * DOC_TBA + */ + ExtentGeometry.prototype.clone = Geometry.prototype.clone; + return ExtentGeometry; }); diff --git a/Source/Core/Geometry.js b/Source/Core/Geometry.js index bf45699a9891..8c85c79ef551 100644 --- a/Source/Core/Geometry.js +++ b/Source/Core/Geometry.js @@ -19,7 +19,7 @@ define([ /** * DOC_TBA */ - this.attributes = options.attributes; + this.attributes = defaultValue(options.attributes, {}); /** * DOC_TBA @@ -32,6 +32,41 @@ define([ this.boundingSphere = options.boundingSphere; }; + /** + * DOC_TBA + */ + Geometry.prototype.clone = function(result) { + if (typeof result === 'undefined') { +// TODO: is this always what we want, for say BoxGeometry? + result = new Geometry(); + } + + var attributes = this.attributes; + var newAttributes = {}; + for (var property in attributes) { + if (attributes.hasOwnProperty(property)) { + newAttributes[property] = attributes[property].clone(); + } + } + result.attributes = newAttributes; + + var indexLists = this.indexLists; + if (typeof indexLists !== 'undefined') { + var length = indexLists.length; + var newIndexLists = new Array(length); + for (var i = 0; i < length; ++i) { + newIndexLists[i] = indexLists[i].clone(); + } + result.indexLists = newIndexLists; + } else { + result.indexLists = undefined; + } + + this.boundingSphere.clone(result.boundingSphere); + + return result; + }; + /** * DOC_TBA * diff --git a/Source/Core/GeometryAttribute.js b/Source/Core/GeometryAttribute.js index b6f3e17119cf..4274fad04da3 100644 --- a/Source/Core/GeometryAttribute.js +++ b/Source/Core/GeometryAttribute.js @@ -35,5 +35,30 @@ define([ this.values = options.values; }; + /** + * DOC_TBA + */ + GeometryAttribute.prototype.clone = function(result) { + if (typeof result === 'undefined') { + result = new GeometryAttribute(); + } + + result.componentDatatype = this.componentDatatype; // Shallow copy enum + result.componentsPerAttribute = this.componentsPerAttribute; + result.normalize = this.normalize; + +// TODO: typed array or not. fastest way to copy? +// TODO: attribute not backed by buffer? + var sourceValues = this.values; + var length = sourceValues.length; + var values = new Array(length); + for (var i = 0; i < length; ++i) { + values[i] = sourceValues[i]; + } + result.values = values; + + return result; + }; + return GeometryAttribute; }); diff --git a/Source/Core/GeometryFilters.js b/Source/Core/GeometryFilters.js index dda040f29f78..d40221d134fc 100644 --- a/Source/Core/GeometryFilters.js +++ b/Source/Core/GeometryFilters.js @@ -238,22 +238,20 @@ define([ //Reorder Vertices var attributes = mesh.attributes; - if (typeof attributes !== 'undefined') { - for ( var property in attributes) { - if (attributes.hasOwnProperty(property) && attributes[property].values) { - var elementsIn = attributes[property].values; - var intoElementsIn = 0; - var numComponents = attributes[property].componentsPerAttribute; - var elementsOut = []; - while (intoElementsIn < numVertices) { - var temp = indexCrossReferenceOldToNew[intoElementsIn]; - for (i = 0; i < numComponents; i++) { - elementsOut[numComponents * temp + i] = elementsIn[numComponents * intoElementsIn + i]; - } - ++intoElementsIn; + for ( var property in attributes) { + if (attributes.hasOwnProperty(property) && attributes[property].values) { + var elementsIn = attributes[property].values; + var intoElementsIn = 0; + var numComponents = attributes[property].componentsPerAttribute; + var elementsOut = []; + while (intoElementsIn < numVertices) { + var temp = indexCrossReferenceOldToNew[intoElementsIn]; + for (i = 0; i < numComponents; i++) { + elementsOut[numComponents * temp + i] = elementsIn[numComponents * intoElementsIn + i]; } - attributes[property].values = elementsOut; + ++intoElementsIn; } + attributes[property].values = elementsOut; } } } @@ -459,7 +457,7 @@ define([ * DOC_TBA */ GeometryFilters.projectTo2D = function(mesh, projection) { - if (typeof mesh !== 'undefined' && typeof mesh.attributes !== 'undefined' && typeof mesh.attributes.position !== 'undefined') { + if (typeof mesh !== 'undefined' && typeof mesh.attributes.position !== 'undefined') { projection = typeof projection !== 'undefined' ? projection : new GeographicProjection(); var ellipsoid = projection.getEllipsoid(); @@ -508,7 +506,6 @@ define([ * @returns The modified mesh argument, with its encoded attribute. * * @exception {DeveloperError} mesh is required. - * @exception {DeveloperError} mesh must have an attributes property. * @exception {DeveloperError} mesh must have attribute matching the attributeName argument. * @exception {DeveloperError} The attribute componentDatatype must be ComponentDatatype.FLOAT. * @@ -526,10 +523,6 @@ define([ throw new DeveloperError('mesh is required.'); } - if (typeof mesh.attributes === 'undefined') { - throw new DeveloperError('mesh must have an attributes property.'); - } - var attribute = mesh.attributes[attributeName]; if (typeof attribute === 'undefined') { @@ -876,8 +869,7 @@ define([ throw new DeveloperError('mesh is required.'); } var attributes = mesh.attributes; - if (typeof attributes === 'undefined' || typeof attributes.position === 'undefined' || - typeof attributes.position.values === 'undefined') { + if (typeof attributes.position === 'undefined' || typeof attributes.position.values === 'undefined') { throw new DeveloperError('mesh.attributes.position.values is required'); } var vertices = mesh.attributes.position.values; @@ -969,9 +961,9 @@ define([ if (typeof mesh.attributes.normal === 'undefined') { mesh.attributes.normal = new GeometryAttribute({ - componentDatatype: ComponentDatatype.FLOAT, - componentsPerAttribute: 3, - values: new Array(numVertices * 3) + componentDatatype: ComponentDatatype.FLOAT, + componentsPerAttribute: 3, + values: new Array(numVertices * 3) }); } var normalValues = mesh.attributes.normal.values; @@ -1030,24 +1022,21 @@ define([ throw new DeveloperError('geometry is required.'); } var attributes = geometry.attributes; - if (typeof attributes === 'undefined' || typeof attributes.position === 'undefined' || - typeof attributes.position.values === 'undefined') { + if (typeof attributes.position === 'undefined' || typeof attributes.position.values === 'undefined') { throw new DeveloperError('geometry.attributes.position.values is required'); } var vertices = geometry.attributes.position.values; if (geometry.attributes.position.componentsPerAttribute !== 3 || vertices.length % 3 !== 0) { throw new DeveloperError('geometry.attributes.position.values.length must be a multiple of 3'); } - if (typeof attributes.normal === 'undefined' || - typeof attributes.normal.values === 'undefined') { + if (typeof attributes.normal === 'undefined' || typeof attributes.normal.values === 'undefined') { throw new DeveloperError('geometry.attributes.normal.values is required'); } var normals = geometry.attributes.normal.values; if (geometry.attributes.normal.componentsPerAttribute !== 3 || normals.length % 3 !== 0) { throw new DeveloperError('geometry.attributes.normals.values.length must be a multiple of 3'); } - if (typeof attributes.st === 'undefined' || - typeof attributes.st.values === 'undefined') { + if (typeof attributes.st === 'undefined' || typeof attributes.st.values === 'undefined') { throw new DeveloperError('geometry.attributes.st.values is required'); } var st = geometry.attributes.st.values; @@ -1138,18 +1127,18 @@ define([ } if (typeof geometry.attributes.tangent === 'undefined') { geometry.attributes.tangent = new GeometryAttribute({ - componentDatatype: ComponentDatatype.FLOAT, - componentsPerAttribute: 3, - values: tangentValues + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : tangentValues }); } else { geometry.attributes.tangent.values = tangentValues; } if (typeof geometry.attributes.binormal === 'undefined') { geometry.attributes.binormal = new GeometryAttribute({ - componentDatatype: ComponentDatatype.FLOAT, - componentsPerAttribute: 3, - values: binormalValues + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : binormalValues }); } else { geometry.attributes.binormal.values = binormalValues; diff --git a/Source/Core/GeometryIndices.js b/Source/Core/GeometryIndices.js index fd9e5d9e59c4..505e86093292 100644 --- a/Source/Core/GeometryIndices.js +++ b/Source/Core/GeometryIndices.js @@ -25,5 +25,27 @@ define([ this.values = options.values; }; + /** + * DOC_TBA + */ + GeometryIndices.prototype.clone = function(result) { + if (typeof result === 'undefined') { + result = new GeometryIndices(); + } + + result.primitiveType = this.primitiveType; // Shallow copy enum + +// TODO: typed array or not. fastest way to copy? + var sourceValues = this.values; + var length = sourceValues.length; + var values = new Array(length); + for (var i = 0; i < length; ++i) { + values[i] = sourceValues[i]; + } + result.values = values; + + return result; + }; + return GeometryIndices; }); diff --git a/Source/Core/GeometryInstance.js b/Source/Core/GeometryInstance.js index 0f6eecc8efb6..b300ba78e346 100644 --- a/Source/Core/GeometryInstance.js +++ b/Source/Core/GeometryInstance.js @@ -14,7 +14,7 @@ define([ * @constructor * * @param {Geometry} [options.geometry] The geometry to instance. - * @param {Matrix4} [options.modelMatrix] The model matrix for this ellipsoid. + * @param {Matrix4} [options.modelMatrix] The model matrix for this geometry. * @param {Color} [options.color] The color of the geometry when a per-geometry color appearance is used. * @param {Object} [options.pickData] DOC_TBA */ @@ -49,5 +49,21 @@ define([ this.pickData = options.pickData; }; + /** + * DOC_TBA + */ + GeometryInstance.prototype.clone = function(result) { + if (typeof result === 'undefined') { + result = new GeometryInstance(); + } + + result.geometry = this.geometry.clone(); + result.modelMatrix = this.modelMatrix.clone(result.modelMatrix); + result.color = (typeof this.color !== 'undefined') ? this.color.clone() : undefined; + result.pickData = this.pickData; // Shadow copy + + return result; + }; + return GeometryInstance; }); diff --git a/Source/Core/Matrix4.js b/Source/Core/Matrix4.js index e7f4a85e9469..6632497b174e 100644 --- a/Source/Core/Matrix4.js +++ b/Source/Core/Matrix4.js @@ -89,32 +89,32 @@ define([ * * @exception {DeveloperError} matrix is required. */ - Matrix4.clone = function(values, result) { - if (typeof values === 'undefined') { - throw new DeveloperError('values is required'); + Matrix4.clone = function(matrix, result) { + if (typeof matrix === 'undefined') { + throw new DeveloperError('matrix is required'); } if (typeof result === 'undefined') { - return new Matrix4(values[0], values[4], values[8], values[12], - values[1], values[5], values[9], values[13], - values[2], values[6], values[10], values[14], - values[3], values[7], values[11], values[15]); + return new Matrix4(matrix[0], matrix[4], matrix[8], matrix[12], + matrix[1], matrix[5], matrix[9], matrix[13], + matrix[2], matrix[6], matrix[10], matrix[14], + matrix[3], matrix[7], matrix[11], matrix[15]); } - result[0] = values[0]; - result[1] = values[1]; - result[2] = values[2]; - result[3] = values[3]; - result[4] = values[4]; - result[5] = values[5]; - result[6] = values[6]; - result[7] = values[7]; - result[8] = values[8]; - result[9] = values[9]; - result[10] = values[10]; - result[11] = values[11]; - result[12] = values[12]; - result[13] = values[13]; - result[14] = values[14]; - result[15] = values[15]; + result[0] = matrix[0]; + result[1] = matrix[1]; + result[2] = matrix[2]; + result[3] = matrix[3]; + result[4] = matrix[4]; + result[5] = matrix[5]; + result[6] = matrix[6]; + result[7] = matrix[7]; + result[8] = matrix[8]; + result[9] = matrix[9]; + result[10] = matrix[10]; + result[11] = matrix[11]; + result[12] = matrix[12]; + result[13] = matrix[13]; + result[14] = matrix[14]; + result[15] = matrix[15]; return result; }; diff --git a/Source/Core/PolygonGeometry.js b/Source/Core/PolygonGeometry.js index e8b3ccab8b7c..1739857d43b0 100644 --- a/Source/Core/PolygonGeometry.js +++ b/Source/Core/PolygonGeometry.js @@ -10,6 +10,7 @@ define([ './DeveloperError', './Ellipsoid', './EllipsoidTangentPlane', + './Geometry', './GeometryAttribute', './GeometryInstance', './GeometryFilters', @@ -32,6 +33,7 @@ define([ DeveloperError, Ellipsoid, EllipsoidTangentPlane, + Geometry, GeometryAttribute, GeometryInstance, GeometryFilters, @@ -427,6 +429,11 @@ define([ this.boundingSphere = boundingSphere; }; + /** + * DOC_TBA + */ + PolygonGeometry.prototype.clone = Geometry.prototype.clone; + return PolygonGeometry; }); diff --git a/Source/Core/WallGeometry.js b/Source/Core/WallGeometry.js index 7231690a11ed..9160fb3fb17c 100644 --- a/Source/Core/WallGeometry.js +++ b/Source/Core/WallGeometry.js @@ -8,6 +8,7 @@ define([ './DeveloperError', './Ellipsoid', './EllipsoidTangentPlane', + './Geometry', './GeometryAttribute', './GeometryIndices', './PolylinePipeline', @@ -24,6 +25,7 @@ define([ DeveloperError, Ellipsoid, EllipsoidTangentPlane, + Geometry, GeometryAttribute, GeometryIndices, PolylinePipeline, @@ -301,6 +303,11 @@ define([ this.boundingSphere = new BoundingSphere.fromVertices(positions); }; + /** + * DOC_TBA + */ + WallGeometry.prototype.clone = Geometry.prototype.clone; + return WallGeometry; }); diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index 866c4b4d73ad..5e27c5e23dce 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -285,28 +285,32 @@ define([ } function geometryPipeline(primitive, instances, context) { - -// TODO: copy instances first since we don't want to modify what they instance. + // Copy instances first since most pipeline operations modify the geometry and instance in-place. + var length = instances.length; + var insts = new Array(length); + for (var i = 0; i < length; ++i) { + insts[i] = instances[i].clone(); + } // Add color attribute if any geometries have per-geometry color - if (hasPerInstanceColor(instances)) { - addColorAttribute(primitive, instances, context); + if (hasPerInstanceColor(insts)) { + addColorAttribute(primitive, insts, context); } // Add pickColor attribute if any geometries are pickable - if (isPickable(instances)) { - addPickColorAttribute(primitive, instances, context); + if (isPickable(insts)) { + addPickColorAttribute(primitive, insts, context); } // Add default values for any undefined attributes - addDefaultAttributes(instances); + addDefaultAttributes(insts); // Unify to world coordinates before combining. If there is only one geometry or all // geometries are in the same (non-world) coordinate system, only combine if the user requested it. - transformToWorldCoordinates(primitive, instances); + transformToWorldCoordinates(primitive, insts); // Combine into single geometry for better rendering performance. - var geometry = GeometryFilters.combine(instances); + var geometry = GeometryFilters.combine(insts); // Split position for GPU RTE GeometryFilters.encodeAttribute(geometry, 'position', 'positionHigh', 'positionLow'); From e7e15a3f78167f04f59348eeb74fa2c474b0c4e6 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Wed, 5 Jun 2013 10:32:26 -0400 Subject: [PATCH 140/306] Change indexLists to a single indexList --- Source/Core/BoxGeometry.js | 94 ++-- Source/Core/CircleGeometry.js | 6 +- Source/Core/EllipseGeometry.js | 14 +- Source/Core/EllipsoidGeometry.js | 14 +- Source/Core/ExtentGeometry.js | 14 +- Source/Core/Geometry.js | 17 +- Source/Core/GeometryFilters.js | 652 +++++++++++------------ Source/Core/PolygonGeometry.js | 6 +- Source/Core/PolygonPipeline.js | 4 +- Source/Core/WallGeometry.js | 14 +- Source/Renderer/Context.js | 15 +- Source/Scene/CentralBody.js | 4 +- Source/Scene/ImageryLayer.js | 4 +- Source/Scene/Primitive.js | 6 +- Specs/Core/BoxGeometrySpec.js | 4 +- Specs/Core/CircleGeometrySpec.js | 4 +- Specs/Core/EllipseGeometrySpec.js | 4 +- Specs/Core/EllipsoidGeometrySpec.js | 4 +- Specs/Core/ExtentGeometrySpec.js | 8 +- Specs/Core/GeometryFiltersSpec.js | 149 +++--- Specs/Core/PolygonGeometrySpec.js | 8 +- Specs/Core/PolygonPipelineSpec.js | 6 +- Specs/Core/WallGeometrySpec.js | 6 +- Specs/Renderer/VertexArrayFactorySpec.js | 24 +- 24 files changed, 486 insertions(+), 595 deletions(-) diff --git a/Source/Core/BoxGeometry.js b/Source/Core/BoxGeometry.js index 43f464d78b4a..5fd6be06be6a 100644 --- a/Source/Core/BoxGeometry.js +++ b/Source/Core/BoxGeometry.js @@ -67,7 +67,7 @@ define([ var vertexFormat = defaultValue(options.vertexFormat, VertexFormat.DEFAULT); var attributes = {}; - var indexLists = []; + var indexList; if (vertexFormat !== VertexFormat.POSITION_ONLY) { @@ -292,36 +292,35 @@ define([ }); } - indexLists.push( - new GeometryIndices({ - // 12 triangles: 6 faces, 2 triangles each. - primitiveType : PrimitiveType.TRIANGLES, - values : [ - // +z face - 0, 1, 2, - 0, 2, 3, + indexList = new GeometryIndices({ + // 12 triangles: 6 faces, 2 triangles each. + primitiveType : PrimitiveType.TRIANGLES, + values : [ + // +z face + 0, 1, 2, + 0, 2, 3, - // -z face - 4 + 2, 4 + 1, 4 + 0, - 4 + 3, 4 + 2, 4 + 0, + // -z face + 4 + 2, 4 + 1, 4 + 0, + 4 + 3, 4 + 2, 4 + 0, - // +x face - 8 + 0, 8 + 1, 8 + 2, - 8 + 0, 8 + 2, 8 + 3, + // +x face + 8 + 0, 8 + 1, 8 + 2, + 8 + 0, 8 + 2, 8 + 3, - // -x face - 12 + 2, 12 + 1, 12 + 0, - 12 + 3, 12 + 2, 12 + 0, + // -x face + 12 + 2, 12 + 1, 12 + 0, + 12 + 3, 12 + 2, 12 + 0, - // +y face - 16 + 2, 16 + 1, 16 + 0, - 16 + 3, 16 + 2, 16 + 0, + // +y face + 16 + 2, 16 + 1, 16 + 0, + 16 + 3, 16 + 2, 16 + 0, - // -y face - 20 + 0, 20 + 1, 20 + 2, - 20 + 0, 20 + 2, 20 + 3 - ] - })); + // -y face + 20 + 0, 20 + 1, 20 + 2, + 20 + 0, 20 + 2, 20 + 3 + ] + }); } else { // Positions only - no need to duplicate corner points attributes.position = new GeometryAttribute({ @@ -340,25 +339,24 @@ define([ ] }); - indexLists.push( - new GeometryIndices({ - // 12 triangles: 6 faces, 2 triangles each. - primitiveType : PrimitiveType.TRIANGLES, - values : [ - 4, 5, 6, // plane z = corner.Z - 4, 6, 7, - 1, 0, 3, // plane z = -corner.Z - 1, 3, 2, - 1, 6, 5, // plane x = corner.X - 1, 2, 6, - 2, 3, 7, // plane y = corner.Y - 2, 7, 6, - 3, 0, 4, // plane x = -corner.X - 3, 4, 7, - 0, 1, 5, // plane y = -corner.Y - 0, 5, 4 - ] - })); + indexList = new GeometryIndices({ + // 12 triangles: 6 faces, 2 triangles each. + primitiveType : PrimitiveType.TRIANGLES, + values : [ + 4, 5, 6, // plane z = corner.Z + 4, 6, 7, + 1, 0, 3, // plane z = -corner.Z + 1, 3, 2, + 1, 6, 5, // plane x = corner.X + 1, 2, 6, + 2, 3, 7, // plane y = corner.Y + 2, 7, 6, + 3, 0, 4, // plane x = -corner.X + 3, 4, 7, + 0, 1, 5, // plane y = -corner.Y + 0, 5, 4 + ] + }); } /** @@ -370,11 +368,11 @@ define([ this.attributes = attributes; /** - * An array of {@link GeometryIndices} defining primitives. + * The geometry indices. * - * @type Array + * @type GeometryIndices */ - this.indexLists = indexLists; + this.indexList = indexList; /** * A tight-fitting bounding sphere that encloses the vertices of the geometry. diff --git a/Source/Core/CircleGeometry.js b/Source/Core/CircleGeometry.js index aa7b7481030a..8023fe1077f6 100644 --- a/Source/Core/CircleGeometry.js +++ b/Source/Core/CircleGeometry.js @@ -66,11 +66,11 @@ define([ this.attributes = ellipseGeometry.attributes; /** - * An array of {@link GeometryIndices} defining primitives. + * The geometry indices. * - * @type Array + * @type GeometryIndices */ - this.indexLists = ellipseGeometry.indexLists; + this.indexList = ellipseGeometry.indexList; /** * A tight-fitting bounding sphere that encloses the vertices of the geometry. diff --git a/Source/Core/EllipseGeometry.js b/Source/Core/EllipseGeometry.js index d1ab933226db..7e050f002e61 100644 --- a/Source/Core/EllipseGeometry.js +++ b/Source/Core/EllipseGeometry.js @@ -432,16 +432,14 @@ define([ this.attributes = attributes; /** - * An array of {@link GeometryIndices} defining primitives. + * The geometry indices. * - * @type Array + * @type GeometryIndices */ - this.indexLists = [ - new GeometryIndices({ - primitiveType : PrimitiveType.TRIANGLES, - values : indices - }) - ]; + this.indexList = new GeometryIndices({ + primitiveType : PrimitiveType.TRIANGLES, + values : indices + }); /** * A tight-fitting bounding sphere that encloses the vertices of the geometry. diff --git a/Source/Core/EllipsoidGeometry.js b/Source/Core/EllipsoidGeometry.js index f7d27d46c87d..2b59ad0e0919 100644 --- a/Source/Core/EllipsoidGeometry.js +++ b/Source/Core/EllipsoidGeometry.js @@ -316,16 +316,14 @@ define([ this.attributes = attributes; /** - * An array of {@link GeometryIndices} defining primitives. + * The geometry indices. * - * @type Array + * @type GeometryIndices */ - this.indexLists = [ - new GeometryIndices({ - primitiveType : PrimitiveType.TRIANGLES, - values : indices - }) - ]; + this.indexList = new GeometryIndices({ + primitiveType : PrimitiveType.TRIANGLES, + values : indices + }); /** * A tight-fitting bounding sphere that encloses the vertices of the geometry. diff --git a/Source/Core/ExtentGeometry.js b/Source/Core/ExtentGeometry.js index 926ef5c81d19..751a1af63083 100644 --- a/Source/Core/ExtentGeometry.js +++ b/Source/Core/ExtentGeometry.js @@ -304,16 +304,14 @@ define([ this.attributes = attributes; /** - * An array of {@link GeometryIndices} defining primitives. + * The geometry indices. * - * @type Array + * @type GeometryIndices */ - this.indexLists = [ - new GeometryIndices({ - primitiveType : PrimitiveType.TRIANGLES, - values : indices - }) - ]; + this.indexList = new GeometryIndices({ + primitiveType : PrimitiveType.TRIANGLES, + values : indices + }); /** * A tight-fitting bounding sphere that encloses the vertices of the geometry. diff --git a/Source/Core/Geometry.js b/Source/Core/Geometry.js index 8c85c79ef551..880069948b61 100644 --- a/Source/Core/Geometry.js +++ b/Source/Core/Geometry.js @@ -24,7 +24,7 @@ define([ /** * DOC_TBA */ - this.indexLists = options.indexLists; + this.indexList = options.indexList; /** * DOC_TBA @@ -48,20 +48,9 @@ define([ newAttributes[property] = attributes[property].clone(); } } - result.attributes = newAttributes; - - var indexLists = this.indexLists; - if (typeof indexLists !== 'undefined') { - var length = indexLists.length; - var newIndexLists = new Array(length); - for (var i = 0; i < length; ++i) { - newIndexLists[i] = indexLists[i].clone(); - } - result.indexLists = newIndexLists; - } else { - result.indexLists = undefined; - } + result.attributes = newAttributes; + result.indexList = (typeof this.indexList !== 'undefined') ? this.indexList.clone() : undefined; this.boundingSphere.clone(result.boundingSphere); return result; diff --git a/Source/Core/GeometryFilters.js b/Source/Core/GeometryFilters.js index d40221d134fc..0cc15420c496 100644 --- a/Source/Core/GeometryFilters.js +++ b/Source/Core/GeometryFilters.js @@ -111,27 +111,21 @@ define([ } if (typeof mesh !== 'undefined') { - var indexLists = mesh.indexLists; - if (typeof indexLists !== 'undefined') { - var count = indexLists.length; - for ( var i = 0; i < count; ++i) { - var indices = indexLists[i]; - - switch (indices.primitiveType) { - case PrimitiveType.TRIANGLES: - indices.primitiveType = PrimitiveType.LINES; - indices.values = trianglesToLines(indices.values); - break; - case PrimitiveType.TRIANGLE_STRIP: - indices.primitiveType = PrimitiveType.LINES; - indices.values = triangleStripToLines(indices.values); - break; - case PrimitiveType.TRIANGLE_FAN: - indices.primitiveType = PrimitiveType.LINES; - indices.values = triangleFanToLines(indices.values); - break; - } + var indices = mesh.indexList; + if (typeof indices !== 'undefined') { + switch (indices.primitiveType) { + case PrimitiveType.TRIANGLES: + indices.values = trianglesToLines(indices.values); + break; + case PrimitiveType.TRIANGLE_STRIP: + indices.values = triangleStripToLines(indices.values); + break; + case PrimitiveType.TRIANGLE_FAN: + indices.values = triangleFanToLines(indices.values); + break; } + + indices.primitiveType = PrimitiveType.LINES; } } @@ -204,36 +198,33 @@ define([ } //Construct cross reference and reorder indices - var indexLists = mesh.indexLists; - if (typeof indexLists !== 'undefined') { - var count = indexLists.length; - for ( var j = 0; j < count; ++j) { - var indicesIn = indexLists[j].values; - var numIndices = indicesIn.length; - var indicesOut = []; - var intoIndicesIn = 0; - var intoIndicesOut = 0; - var nextIndex = 0; - var tempIndex; - while (intoIndicesIn < numIndices) { - tempIndex = indexCrossReferenceOldToNew[indicesIn[intoIndicesIn]]; - if (tempIndex !== -1) { - indicesOut[intoIndicesOut] = tempIndex; - } else { - tempIndex = indicesIn[intoIndicesIn]; - if (tempIndex >= numVertices) { - throw new DeveloperError('Input indices contains a value greater than or equal to the number of vertices'); - } - indexCrossReferenceOldToNew[tempIndex] = nextIndex; - - indicesOut[intoIndicesOut] = nextIndex; - ++nextIndex; + var indexList = mesh.indexList; + if (typeof indexList !== 'undefined') { + var indicesIn = indexList.values; + var numIndices = indicesIn.length; + var indicesOut = []; + var intoIndicesIn = 0; + var intoIndicesOut = 0; + var nextIndex = 0; + var tempIndex; + while (intoIndicesIn < numIndices) { + tempIndex = indexCrossReferenceOldToNew[indicesIn[intoIndicesIn]]; + if (tempIndex !== -1) { + indicesOut[intoIndicesOut] = tempIndex; + } else { + tempIndex = indicesIn[intoIndicesIn]; + if (tempIndex >= numVertices) { + throw new DeveloperError('Input indices contains a value greater than or equal to the number of vertices'); } - ++intoIndicesIn; - ++intoIndicesOut; + indexCrossReferenceOldToNew[tempIndex] = nextIndex; + + indicesOut[intoIndicesOut] = nextIndex; + ++nextIndex; } - indexLists[j].values = indicesOut; + ++intoIndicesIn; + ++intoIndicesOut; } + mesh.indexList.values = indicesOut; } //Reorder Vertices @@ -287,38 +278,25 @@ define([ */ GeometryFilters.reorderForPostVertexCache = function(mesh, cacheCapacity) { if (typeof mesh !== 'undefined') { - var indexLists = mesh.indexLists; - if (typeof indexLists !== 'undefined') { - var count = indexLists.length; - for ( var i = 0; i < count; i++) { - var indices = indexLists[i].values; - var numIndices = indices.length; - var maximumIndex = 0; - for ( var j = 0; j < numIndices; j++) { - if (indices[j] > maximumIndex) { - maximumIndex = indices[j]; - } + var indices = mesh.indexList.values; + if (typeof indices !== 'undefined') { + var numIndices = indices.length; + var maximumIndex = 0; + for ( var j = 0; j < numIndices; j++) { + if (indices[j] > maximumIndex) { + maximumIndex = indices[j]; } - indexLists[i].values = Tipsify.tipsify({ - indices : indices, - maximumIndex : maximumIndex, - cacheSize : cacheCapacity - }); } + mesh.indexList.values = Tipsify.tipsify({ + indices : indices, + maximumIndex : maximumIndex, + cacheSize : cacheCapacity + }); } } return mesh; }; - GeometryFilters._verifyTrianglesPrimitiveType = function(indexLists) { - var length = indexLists.length; - for ( var i = 0; i < length; ++i) { - if (indexLists[i].primitiveType !== PrimitiveType.TRIANGLES) { - throw new DeveloperError('indexLists must have PrimitiveType equal to PrimitiveType.TRIANGLES.'); - } - } - }; - GeometryFilters._copyAttributesDescriptions = function(attributes) { var newAttributes = {}; @@ -359,10 +337,10 @@ define([ function createMesh(attributes, primitiveType, indices) { return new Geometry({ attributes : attributes, - indexLists : [new GeometryIndices({ + indexList : new GeometryIndices({ primitiveType : primitiveType, values : indices - })], + }), boundingSphere : (typeof mesh.boundingSphere !== 'undefined') ? BoundingSphere.clone(mesh.boundingSphere) : undefined, modelMatrix : (typeof mesh.modelMatrix !== 'undefined') ? Matrix4.clone(mesh.modelMatrix) : undefined, pickData : mesh.pickData @@ -372,78 +350,73 @@ define([ var meshes = []; if (typeof mesh !== 'undefined') { - GeometryFilters._verifyTrianglesPrimitiveType(mesh.indexLists); + if (mesh.indexList.primitiveType !== PrimitiveType.TRIANGLES) { + throw new DeveloperError('indexList must have PrimitiveType equal to PrimitiveType.TRIANGLES.'); + } var numberOfVertices = Geometry.computeNumberOfVertices(mesh); // If there's an index list and more than 64K attributes, it is possible that // some indices are outside the range of unsigned short [0, 64K - 1] var sixtyFourK = 64 * 1024; - var indexLists = mesh.indexLists; - if (typeof indexLists !== 'undefined' && (numberOfVertices > sixtyFourK)) { - // PERFORMANCE_IDEA: If an input mesh has more than one index-list. This creates - // at least one vertex-array per index-list. A more sophisticated implementation - // may create less vertex-arrays. - var length = indexLists.length; - for ( var i = 0; i < length; ++i) { - var oldToNewIndex = []; - var newIndices = []; - var currentIndex = 0; - var newAttributes = GeometryFilters._copyAttributesDescriptions(mesh.attributes); - - var originalIndices = indexLists[i].values; - var numberOfIndices = originalIndices.length; - - for ( var j = 0; j < numberOfIndices; j += 3) { - // It would be easy to extend this inter-loop to support all primitive-types. - - var x0 = originalIndices[j]; - var x1 = originalIndices[j + 1]; - var x2 = originalIndices[j + 2]; - - var i0 = oldToNewIndex[x0]; - if (typeof i0 === 'undefined') { - i0 = currentIndex++; - oldToNewIndex[x0] = i0; - - copyVertex(newAttributes, mesh.attributes, x0); - } + if (typeof mesh.indexList !== 'undefined' && (numberOfVertices > sixtyFourK)) { + var oldToNewIndex = []; + var newIndices = []; + var currentIndex = 0; + var newAttributes = GeometryFilters._copyAttributesDescriptions(mesh.attributes); - var i1 = oldToNewIndex[x1]; - if (typeof i1 === 'undefined') { - i1 = currentIndex++; - oldToNewIndex[x1] = i1; + var originalIndices = mesh.indexList.values; + var numberOfIndices = originalIndices.length; - copyVertex(newAttributes, mesh.attributes, x1); - } + for ( var j = 0; j < numberOfIndices; j += 3) { + // It would be easy to extend this inter-loop to support all primitive-types. - var i2 = oldToNewIndex[x2]; - if (typeof i2 === 'undefined') { - i2 = currentIndex++; - oldToNewIndex[x2] = i2; + var x0 = originalIndices[j]; + var x1 = originalIndices[j + 1]; + var x2 = originalIndices[j + 2]; - copyVertex(newAttributes, mesh.attributes, x2); - } + var i0 = oldToNewIndex[x0]; + if (typeof i0 === 'undefined') { + i0 = currentIndex++; + oldToNewIndex[x0] = i0; - newIndices.push(i0); - newIndices.push(i1); - newIndices.push(i2); + copyVertex(newAttributes, mesh.attributes, x0); + } - if (currentIndex + 3 > sixtyFourK) { - meshes.push(createMesh(newAttributes, indexLists[i].primitiveType, newIndices)); + var i1 = oldToNewIndex[x1]; + if (typeof i1 === 'undefined') { + i1 = currentIndex++; + oldToNewIndex[x1] = i1; - // Reset for next vertex-array - oldToNewIndex = []; - newIndices = []; - currentIndex = 0; - newAttributes = GeometryFilters._copyAttributesDescriptions(mesh.attributes); - } + copyVertex(newAttributes, mesh.attributes, x1); } - if (newIndices.length !== 0) { - meshes.push(createMesh(newAttributes, indexLists[i].primitiveType, newIndices)); + var i2 = oldToNewIndex[x2]; + if (typeof i2 === 'undefined') { + i2 = currentIndex++; + oldToNewIndex[x2] = i2; + + copyVertex(newAttributes, mesh.attributes, x2); + } + + newIndices.push(i0); + newIndices.push(i1); + newIndices.push(i2); + + if (currentIndex + 3 > sixtyFourK) { + meshes.push(createMesh(newAttributes, mesh.indexList.primitiveType, newIndices)); + + // Reset for next vertex-array + oldToNewIndex = []; + newIndices = []; + currentIndex = 0; + newAttributes = GeometryFilters._copyAttributesDescriptions(mesh.attributes); } } + + if (newIndices.length !== 0) { + meshes.push(createMesh(newAttributes, mesh.indexList.primitiveType, newIndices)); + } } else { // No need to split into multiple meshes meshes.push(mesh); @@ -745,20 +718,12 @@ define([ // First, determine the size of a typed array per primitive type var numberOfIndices = {}; - var indexLists; - var indexListsLength; var indices; for (i = 0; i < length; ++i) { - indexLists = instances[i].geometry.indexLists; - indexListsLength = indexLists.length; - - for (j = 0; j < indexListsLength; ++j) { - indices = indexLists[j]; - - numberOfIndices[indices.primitiveType] = (typeof numberOfIndices[indices.primitiveType] !== 'undefined') ? - (numberOfIndices[indices.primitiveType] += indices.values.length) : indices.values.length; - } + indices = instances[i].geometry.indexList; + numberOfIndices[indices.primitiveType] = (typeof numberOfIndices[indices.primitiveType] !== 'undefined') ? + (numberOfIndices[indices.primitiveType] += indices.values.length) : indices.values.length; } // Next, allocate a typed array for indices per primitive type @@ -792,23 +757,18 @@ define([ var offset = 0; for (i = 0; i < length; ++i) { - indexLists = instances[i].geometry.indexLists; - indexListsLength = indexLists.length; - - for (j = 0; j < indexListsLength; ++j) { - indices = indexLists[j]; - sourceValues = indices.values; - sourceValuesLength = sourceValues.length; - var destValues = indexListsByPrimitiveType[indices.primitiveType].values; - var n = indexListsByPrimitiveType[indices.primitiveType].currentOffset; - - for (k = 0; k < sourceValuesLength; ++k) { - destValues[n++] = offset + sourceValues[k]; - } - - indexListsByPrimitiveType[indices.primitiveType].currentOffset = n; + indices = instances[i].geometry.indexList; + sourceValues = indices.values; + sourceValuesLength = sourceValues.length; + var destValues = indexListsByPrimitiveType[indices.primitiveType].values; + var n = indexListsByPrimitiveType[indices.primitiveType].currentOffset; + + for (k = 0; k < sourceValuesLength; ++k) { + destValues[n++] = offset + sourceValues[k]; } + indexListsByPrimitiveType[indices.primitiveType].currentOffset = n; + var attrs = instances[i].geometry.attributes; for (name in attrs) { if (attrs.hasOwnProperty(name)) { @@ -838,7 +798,8 @@ define([ return new Geometry({ attributes : attributes, - indexLists : combinedIndexLists, +// TODO: cleanup combinedIndexLists + indexList : combinedIndexLists[0], boundingSphere : boundingSphere }); }; @@ -876,114 +837,111 @@ define([ if (mesh.attributes.position.componentsPerAttribute !== 3 || vertices.length % 3 !== 0) { throw new DeveloperError('mesh.attributes.position.values.length must be a multiple of 3'); } - var indexLists = mesh.indexLists; - if (typeof indexLists === 'undefined') { + var indexList = mesh.indexList; + if (typeof indexList === 'undefined') { return mesh; } - var length = indexLists.length; - for (var k = 0; k < length; k++) { - var indices = indexLists[k].values; - if (indexLists[k].primitiveType !== PrimitiveType.TRIANGLES || typeof indices === 'undefined' || - indices.length < 2 || indices.length % 3 !== 0) { - continue; - } + var indices = indexList.values; + if (indexList.primitiveType !== PrimitiveType.TRIANGLES || typeof indices === 'undefined' || + indices.length < 2 || indices.length % 3 !== 0) { + return mesh; + } - var numVertices = mesh.attributes.position.values.length/3; - var numIndices = indices.length; - var normalsPerVertex = new Array(numVertices); - var normalsPerTriangle = new Array(numIndices/3); - var normalIndices = new Array(numIndices); - - for (var i = 0; i < numVertices; i++) { - normalsPerVertex[i] = { - indexOffset: 0, - count: 0, - currentCount: 0 - }; - } + var numVertices = mesh.attributes.position.values.length / 3; + var numIndices = indices.length; + var normalsPerVertex = new Array(numVertices); + var normalsPerTriangle = new Array(numIndices / 3); + var normalIndices = new Array(numIndices); + + for (var i = 0; i < numVertices; i++) { + normalsPerVertex[i] = { + indexOffset : 0, + count : 0, + currentCount : 0 + }; + } - var j = 0; - for (i = 0; i < numIndices; i+=3) { - var i0 = indices[i]; - var i1 = indices[i+1]; - var i2 = indices[i+2]; - var i03 = i0*3; - var i13 = i1*3; - var i23 = i2*3; - - v0.x = vertices[i03]; - v0.y = vertices[i03+1]; - v0.z = vertices[i03+2]; - v1.x = vertices[i13]; - v1.y = vertices[i13+1]; - v1.z = vertices[i13+2]; - v2.x = vertices[i23]; - v2.y = vertices[i23+1]; - v2.z = vertices[i23+2]; - - normalsPerVertex[i0].count++; - normalsPerVertex[i1].count++; - normalsPerVertex[i2].count++; - - v1.subtract(v0, v1); - v2.subtract(v0, v2); - normalsPerTriangle[j] = v1.cross(v2); - j++; - } + var j = 0; + for (i = 0; i < numIndices; i += 3) { + var i0 = indices[i]; + var i1 = indices[i + 1]; + var i2 = indices[i + 2]; + var i03 = i0*3; + var i13 = i1*3; + var i23 = i2*3; + + v0.x = vertices[i03]; + v0.y = vertices[i03 + 1]; + v0.z = vertices[i03 + 2]; + v1.x = vertices[i13]; + v1.y = vertices[i13 + 1]; + v1.z = vertices[i13 + 2]; + v2.x = vertices[i23]; + v2.y = vertices[i23 + 1]; + v2.z = vertices[i23 + 2]; + + normalsPerVertex[i0].count++; + normalsPerVertex[i1].count++; + normalsPerVertex[i2].count++; + + v1.subtract(v0, v1); + v2.subtract(v0, v2); + normalsPerTriangle[j] = v1.cross(v2); + j++; + } - var indexOffset = 0; - for (i = 0; i < numVertices; i++) { - normalsPerVertex[i].indexOffset += indexOffset; - indexOffset += normalsPerVertex[i].count; - } + var indexOffset = 0; + for (i = 0; i < numVertices; i++) { + normalsPerVertex[i].indexOffset += indexOffset; + indexOffset += normalsPerVertex[i].count; + } - j = 0; - var vertexNormalData; - for (i = 0; i < numIndices; i+=3) { - vertexNormalData = normalsPerVertex[indices[i]]; - var index = vertexNormalData.indexOffset + vertexNormalData.currentCount; - normalIndices[index] = j; - vertexNormalData.currentCount++; - - vertexNormalData = normalsPerVertex[indices[i+1]]; - index = vertexNormalData.indexOffset + vertexNormalData.currentCount; - normalIndices[index] = j; - vertexNormalData.currentCount++; - - vertexNormalData = normalsPerVertex[indices[i+2]]; - index = vertexNormalData.indexOffset + vertexNormalData.currentCount; - normalIndices[index] = j; - vertexNormalData.currentCount++; - - j++; - } + j = 0; + var vertexNormalData; + for (i = 0; i < numIndices; i += 3) { + vertexNormalData = normalsPerVertex[indices[i]]; + var index = vertexNormalData.indexOffset + vertexNormalData.currentCount; + normalIndices[index] = j; + vertexNormalData.currentCount++; + + vertexNormalData = normalsPerVertex[indices[i + 1]]; + index = vertexNormalData.indexOffset + vertexNormalData.currentCount; + normalIndices[index] = j; + vertexNormalData.currentCount++; + + vertexNormalData = normalsPerVertex[indices[i + 2]]; + index = vertexNormalData.indexOffset + vertexNormalData.currentCount; + normalIndices[index] = j; + vertexNormalData.currentCount++; + + j++; + } - if (typeof mesh.attributes.normal === 'undefined') { - mesh.attributes.normal = new GeometryAttribute({ - componentDatatype: ComponentDatatype.FLOAT, - componentsPerAttribute: 3, - values: new Array(numVertices * 3) - }); - } - var normalValues = mesh.attributes.normal.values; - for (i = 0; i < numVertices; i++) { - var i3 = i * 3; - vertexNormalData = normalsPerVertex[i]; - if (vertexNormalData.count > 0) { - Cartesian3.ZERO.clone(normal); - for (j = 0; j < vertexNormalData.count; j++) { - normal.add(normalsPerTriangle[normalIndices[vertexNormalData.indexOffset + j]], normal); - } - normal.normalize(normal); - normalValues[i3] = normal.x; - normalValues[i3+1] = normal.y; - normalValues[i3+2] = normal.z; - } else { - normalValues[i3] = 0; - normalValues[i3+1] = 0; - normalValues[i3+2] = 1; + if (typeof mesh.attributes.normal === 'undefined') { + mesh.attributes.normal = new GeometryAttribute({ + componentDatatype: ComponentDatatype.FLOAT, + componentsPerAttribute: 3, + values: new Array(numVertices * 3) + }); + } + var normalValues = mesh.attributes.normal.values; + for (i = 0; i < numVertices; i++) { + var i3 = i * 3; + vertexNormalData = normalsPerVertex[i]; + if (vertexNormalData.count > 0) { + Cartesian3.ZERO.clone(normal); + for (j = 0; j < vertexNormalData.count; j++) { + normal.add(normalsPerTriangle[normalIndices[vertexNormalData.indexOffset + j]], normal); } + normal.normalize(normal); + normalValues[i3] = normal.x; + normalValues[i3+1] = normal.y; + normalValues[i3+2] = normal.z; + } else { + normalValues[i3] = 0.0; + normalValues[i3+1] = 0.0; + normalValues[i3+2] = 1.0; } } @@ -1044,106 +1002,104 @@ define([ throw new DeveloperError('geometry.attributes.st.values.length must be a multiple of 2'); } - var indexLists = geometry.indexLists; - if (typeof indexLists === 'undefined') { + var indexList = geometry.indexList; + if (typeof indexList === 'undefined') { return geometry; } - var length = indexLists.length; - for (var k = 0; k < length; k++) { - var indices = indexLists[k].values; - if (indexLists[k].primitiveType !== PrimitiveType.TRIANGLES || typeof indices === 'undefined' || - indices.length < 2 || indices.length % 3 !== 0) { - continue; - } + var indices = indexList.values; + if (indexList.primitiveType !== PrimitiveType.TRIANGLES || typeof indices === 'undefined' || + indices.length < 2 || indices.length % 3 !== 0) { + return geometry; + } - var numVertices = geometry.attributes.position.values.length/3; - var numIndices = indices.length; - var tan1 = new Array(numVertices*3); + var numVertices = geometry.attributes.position.values.length/3; + var numIndices = indices.length; + var tan1 = new Array(numVertices * 3); - for (var i = 0; i < tan1.length; i++) { - tan1[i] = 0; - } + for (var i = 0; i < tan1.length; i++) { + tan1[i] = 0; + } - var i03; - var i13; - var i23; - for (i = 0; i < numIndices; i+=3) { - var i0 = indices[i]; - var i1 = indices[i+1]; - var i2 = indices[i+2]; - i03 = i0*3; - i13 = i1*3; - i23 = i2*3; - var i02 = i0*2; - var i12 = i1*2; - var i22 = i2*2; - - var ux = vertices[i03]; - var uy = vertices[i03+1]; - var uz = vertices[i03+2]; - - var wx = st[i02]; - var wy = st[i02+1]; - var t1 = st[i12+1] - wy; - var t2 = st[i22+1] - wy; - - var r = 1.0/((st[i12] - wx) * t2 - (st[i22] - wx) * t1); - var sdirx = (t2 * (vertices[i13] - ux) - t1 * (vertices[i23] - ux)) * r; - var sdiry = (t2 * (vertices[i13+1] - uy) - t1 * (vertices[i23+1] - uy)) * r; - var sdirz = (t2 * (vertices[i13+2] - uz) - t1 * (vertices[i23+2] - uz)) * r; - - tan1[i03] += sdirx; - tan1[i03+1] += sdiry; - tan1[i03+2] += sdirz; - - tan1[i13] += sdirx; - tan1[i13+1] += sdiry; - tan1[i13+2] += sdirz; - - tan1[i23] += sdirx; - tan1[i23+1] += sdiry; - tan1[i23+2] += sdirz; - } - var binormalValues = new Array(numVertices * 3); - var tangentValues = new Array(numVertices * 3); - for (i = 0; i < numVertices; i++) { - i03 = i*3; - i13 = i03+1; - i23 = i03+2; - - var n = Cartesian3.fromArray(normals, i03, normalScratch); - var t = Cartesian3.fromArray(tan1, i03, tScratch); - var scalar = n.dot(t); - n.multiplyByScalar(scalar, normalScale); - t.subtract(normalScale, t).normalize(t); - tangentValues[i03] = t.x; - tangentValues[i13] = t.y; - tangentValues[i23] = t.z; - n.cross(t, t).normalize(t); - binormalValues[i03] = t.x; - binormalValues[i13] = t.y; - binormalValues[i23] = t.z; - } - if (typeof geometry.attributes.tangent === 'undefined') { - geometry.attributes.tangent = new GeometryAttribute({ - componentDatatype : ComponentDatatype.FLOAT, - componentsPerAttribute : 3, - values : tangentValues - }); - } else { - geometry.attributes.tangent.values = tangentValues; - } - if (typeof geometry.attributes.binormal === 'undefined') { - geometry.attributes.binormal = new GeometryAttribute({ - componentDatatype : ComponentDatatype.FLOAT, - componentsPerAttribute : 3, - values : binormalValues - }); - } else { - geometry.attributes.binormal.values = binormalValues; - } + var i03; + var i13; + var i23; + for (i = 0; i < numIndices; i+=3) { + var i0 = indices[i]; + var i1 = indices[i + 1]; + var i2 = indices[i + 2]; + i03 = i0*3; + i13 = i1*3; + i23 = i2*3; + var i02 = i0*2; + var i12 = i1*2; + var i22 = i2*2; + + var ux = vertices[i03]; + var uy = vertices[i03 + 1]; + var uz = vertices[i03 + 2]; + + var wx = st[i02]; + var wy = st[i02 + 1]; + var t1 = st[i12 + 1] - wy; + var t2 = st[i22 + 1] - wy; + + var r = 1.0 / ((st[i12] - wx) * t2 - (st[i22] - wx) * t1); + var sdirx = (t2 * (vertices[i13] - ux) - t1 * (vertices[i23] - ux)) * r; + var sdiry = (t2 * (vertices[i13 + 1] - uy) - t1 * (vertices[i23 + 1] - uy)) * r; + var sdirz = (t2 * (vertices[i13 + 2] - uz) - t1 * (vertices[i23 + 2] - uz)) * r; + + tan1[i03] += sdirx; + tan1[i03+1] += sdiry; + tan1[i03+2] += sdirz; + + tan1[i13] += sdirx; + tan1[i13+1] += sdiry; + tan1[i13+2] += sdirz; + + tan1[i23] += sdirx; + tan1[i23+1] += sdiry; + tan1[i23+2] += sdirz; + } + var binormalValues = new Array(numVertices * 3); + var tangentValues = new Array(numVertices * 3); + for (i = 0; i < numVertices; i++) { + i03 = i * 3; + i13 = i03 + 1; + i23 = i03 + 2; + + var n = Cartesian3.fromArray(normals, i03, normalScratch); + var t = Cartesian3.fromArray(tan1, i03, tScratch); + var scalar = n.dot(t); + n.multiplyByScalar(scalar, normalScale); + t.subtract(normalScale, t).normalize(t); + tangentValues[i03] = t.x; + tangentValues[i13] = t.y; + tangentValues[i23] = t.z; + n.cross(t, t).normalize(t); + binormalValues[i03] = t.x; + binormalValues[i13] = t.y; + binormalValues[i23] = t.z; + } + if (typeof geometry.attributes.tangent === 'undefined') { + geometry.attributes.tangent = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : tangentValues + }); + } else { + geometry.attributes.tangent.values = tangentValues; } + if (typeof geometry.attributes.binormal === 'undefined') { + geometry.attributes.binormal = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : binormalValues + }); + } else { + geometry.attributes.binormal.values = binormalValues; + } + return geometry; }; diff --git a/Source/Core/PolygonGeometry.js b/Source/Core/PolygonGeometry.js index 1739857d43b0..ae0ef83a79ef 100644 --- a/Source/Core/PolygonGeometry.js +++ b/Source/Core/PolygonGeometry.js @@ -415,11 +415,11 @@ define([ this.attributes = attributes; /** - * An array of {@link GeometryIndices} defining primitives. + * The geometry indices. * - * @type Array + * @type GeometryIndices */ - this.indexLists = mesh.indexLists; + this.indexList = mesh.indexList; /** * A tight-fitting bounding sphere that encloses the vertices of the geometry. diff --git a/Source/Core/PolygonPipeline.js b/Source/Core/PolygonPipeline.js index 2533c7936e07..f6aaeda89f0f 100644 --- a/Source/Core/PolygonPipeline.js +++ b/Source/Core/PolygonPipeline.js @@ -838,10 +838,10 @@ define([ }) }, - indexLists : [new GeometryIndices({ + indexList : new GeometryIndices({ primitiveType : PrimitiveType.TRIANGLES, values : subdividedIndices - })] + }) }); }, diff --git a/Source/Core/WallGeometry.js b/Source/Core/WallGeometry.js index 9160fb3fb17c..98257a0719a3 100644 --- a/Source/Core/WallGeometry.js +++ b/Source/Core/WallGeometry.js @@ -284,16 +284,14 @@ define([ this.attributes = attributes; /** - * An array of {@link GeometryIndices} defining primitives. + * The geometry indices. * - * @type Array + * @type GeometryIndices */ - this.indexLists = [ - new GeometryIndices({ - primitiveType : PrimitiveType.TRIANGLES, - values : indices - }) - ]; + this.indexList = new GeometryIndices({ + primitiveType : PrimitiveType.TRIANGLES, + values : indices + }); /** * A tight-fitting bounding sphere that encloses the vertices of the geometry. diff --git a/Source/Renderer/Context.js b/Source/Renderer/Context.js index 0efc09666e7e..65faa9cacbe0 100644 --- a/Source/Renderer/Context.js +++ b/Source/Renderer/Context.js @@ -2351,14 +2351,6 @@ define([ var mesh = defaultValue(ca.mesh, defaultValue.EMPTY_OBJECT); var bufferUsage = defaultValue(ca.bufferUsage, BufferUsage.DYNAMIC_DRAW); - var indexLists; - - if (mesh.indexLists) { - indexLists = mesh.indexLists; - if (indexLists.length !== 1) { - throw new DeveloperError('The mesh must have zero or one index lists. This mesh has ' + indexLists.length.toString() + ' index lists.'); - } - } var attributeIndices = defaultValue(ca.attributeIndices, defaultValue.EMPTY_OBJECT); var interleave = ca.vertexLayout && (ca.vertexLayout === VertexLayout.INTERLEAVED); @@ -2421,11 +2413,12 @@ define([ } var indexBuffer; - if (typeof indexLists !== 'undefined') { + var indexList = mesh.indexList; + if (typeof indexList !== 'undefined') { if ((Geometry.computeNumberOfVertices(mesh) > 64 * 1024) && this.getElementIndexUint()) { - indexBuffer = this.createIndexBuffer(new Uint32Array(indexLists[0].values), bufferUsage, IndexDatatype.UNSIGNED_INT); + indexBuffer = this.createIndexBuffer(new Uint32Array(indexList.values), bufferUsage, IndexDatatype.UNSIGNED_INT); } else{ - indexBuffer = this.createIndexBuffer(new Uint16Array(indexLists[0].values), bufferUsage, IndexDatatype.UNSIGNED_SHORT); + indexBuffer = this.createIndexBuffer(new Uint16Array(indexList.values), bufferUsage, IndexDatatype.UNSIGNED_SHORT); } } diff --git a/Source/Scene/CentralBody.js b/Source/Scene/CentralBody.js index 190d529afb6c..493e5d19574e 100644 --- a/Source/Scene/CentralBody.js +++ b/Source/Scene/CentralBody.js @@ -549,10 +549,10 @@ define([ values : depthQuad } }, - indexLists : [{ + indexList : { primitiveType : PrimitiveType.TRIANGLES, values : [0, 1, 2, 2, 1, 3] - }] + } }; this._depthCommand.vertexArray = context.createVertexArrayFromMesh({ mesh : mesh, diff --git a/Source/Scene/ImageryLayer.js b/Source/Scene/ImageryLayer.js index f4e92587aba0..132d944039e0 100644 --- a/Source/Scene/ImageryLayer.js +++ b/Source/Scene/ImageryLayer.js @@ -803,10 +803,10 @@ define([ values : positions } }, - indexLists : [{ + indexList : { primitiveType : PrimitiveType.TRIANGLES, values : TerrainProvider.getRegularGridIndices(256, 256) - }] + } }; var reprojectAttribInds = { diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index 5e27c5e23dce..418ad15d142b 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -399,8 +399,8 @@ define([ var geometry = geometries[i]; var command = new DrawCommand(); -// TODO: this assumes indices in the geometries - and only one set - command.primitiveType = geometry.indexLists[0].primitiveType; +// TODO: this assumes indices in the geometries + command.primitiveType = geometry.indexList.primitiveType; command.vertexArray = this._va[i]; command.renderState = rs; command.shaderProgram = this._sp; @@ -409,7 +409,7 @@ define([ colorCommands.push(command); var pickCommand = new DrawCommand(); - pickCommand.primitiveType = geometry.indexLists[0].primitiveType; + pickCommand.primitiveType = geometry.indexList.primitiveType; pickCommand.vertexArray = this._va[i]; pickCommand.renderState = pickRS; pickCommand.shaderProgram = this._pickSP; diff --git a/Specs/Core/BoxGeometrySpec.js b/Specs/Core/BoxGeometrySpec.js index bdb28d33a441..30d49d0f08e0 100644 --- a/Specs/Core/BoxGeometrySpec.js +++ b/Specs/Core/BoxGeometrySpec.js @@ -27,7 +27,7 @@ defineSuite([ }); expect(m.attributes.position.values.length).toEqual(8 * 3); - expect(m.indexLists[0].values.length).toEqual(12 * 3); + expect(m.indexList.values.length).toEqual(12 * 3); }); it('constructor computes all vertex attributes', function() { @@ -45,7 +45,7 @@ defineSuite([ expect(m.attributes.binormal.values.length).toEqual(6 * 4 * 3); expect(m.attributes.st.values.length).toEqual(6 * 4 * 2); - expect(m.indexLists[0].values.length).toEqual(12 * 3); + expect(m.indexList.values.length).toEqual(12 * 3); expect(m.boundingSphere.center).toEqual(Cartesian3.ZERO); expect(m.boundingSphere.radius).toEqual(maximumCorner.magnitude() * 0.5); diff --git a/Specs/Core/CircleGeometrySpec.js b/Specs/Core/CircleGeometrySpec.js index cf8a85a41922..81af07b3f8b4 100644 --- a/Specs/Core/CircleGeometrySpec.js +++ b/Specs/Core/CircleGeometrySpec.js @@ -60,7 +60,7 @@ defineSuite([ }); expect(m.attributes.position.values.length).toEqual(3 * 24); - expect(m.indexLists[0].values.length).toEqual(3 * 34); + expect(m.indexList.values.length).toEqual(3 * 34); expect(m.boundingSphere.radius).toEqual(1); }); @@ -79,6 +79,6 @@ defineSuite([ expect(m.attributes.normal.values.length).toEqual(3 * 24); expect(m.attributes.tangent.values.length).toEqual(3 * 24); expect(m.attributes.binormal.values.length).toEqual(3 * 24); - expect(m.indexLists[0].values.length).toEqual(3 * 34); + expect(m.indexList.values.length).toEqual(3 * 34); }); }); diff --git a/Specs/Core/EllipseGeometrySpec.js b/Specs/Core/EllipseGeometrySpec.js index baf1f752281f..8436bf7dff21 100644 --- a/Specs/Core/EllipseGeometrySpec.js +++ b/Specs/Core/EllipseGeometrySpec.js @@ -74,7 +74,7 @@ defineSuite([ }); expect(m.attributes.position.values.length).toEqual(3 * 24); - expect(m.indexLists[0].values.length).toEqual(3 * 34); + expect(m.indexList.values.length).toEqual(3 * 34); expect(m.boundingSphere.radius).toEqual(1); }); @@ -94,6 +94,6 @@ defineSuite([ expect(m.attributes.normal.values.length).toEqual(3 * 24); expect(m.attributes.tangent.values.length).toEqual(3 * 24); expect(m.attributes.binormal.values.length).toEqual(3 * 24); - expect(m.indexLists[0].values.length).toEqual(3 * 34); + expect(m.indexList.values.length).toEqual(3 * 34); }); }); diff --git a/Specs/Core/EllipsoidGeometrySpec.js b/Specs/Core/EllipsoidGeometrySpec.js index cca9cf9da5ae..1f563bc6bd59 100644 --- a/Specs/Core/EllipsoidGeometrySpec.js +++ b/Specs/Core/EllipsoidGeometrySpec.js @@ -30,7 +30,7 @@ defineSuite([ }); expect(m.attributes.position.values.length).toEqual(3 * 8); - expect(m.indexLists[0].values.length).toEqual(12 * 3); + expect(m.indexList.values.length).toEqual(12 * 3); expect(m.boundingSphere.radius).toEqual(1); }); @@ -46,7 +46,7 @@ defineSuite([ expect(m.attributes.normal.values.length).toEqual(3 * (8 + 6 + 12)); expect(m.attributes.tangent.values.length).toEqual(3 * (8 + 6 + 12)); expect(m.attributes.binormal.values.length).toEqual(3 * (8 + 6 + 12)); - expect(m.indexLists[0].values.length).toEqual(2 * 3 * 4 * 6); + expect(m.indexList.values.length).toEqual(2 * 3 * 4 * 6); }); it('computes attributes for a unit sphere', function() { diff --git a/Specs/Core/ExtentGeometrySpec.js b/Specs/Core/ExtentGeometrySpec.js index 657af0a0c791..0e039d3b60c7 100644 --- a/Specs/Core/ExtentGeometrySpec.js +++ b/Specs/Core/ExtentGeometrySpec.js @@ -31,7 +31,7 @@ defineSuite([ var length = positions.length; expect(positions.length).toEqual(9 * 3); - expect(m.indexLists[0].values.length).toEqual(8 * 3); + expect(m.indexList.values.length).toEqual(8 * 3); var expectedNWCorner = Ellipsoid.WGS84.cartographicToCartesian(extent.getNorthwest()); var expectedSECorner = Ellipsoid.WGS84.cartographicToCartesian(extent.getSoutheast()); @@ -50,7 +50,7 @@ defineSuite([ expect(m.attributes.normal.values.length).toEqual(9 * 3); expect(m.attributes.tangent.values.length).toEqual(9 * 3); expect(m.attributes.binormal.values.length).toEqual(9 * 3); - expect(m.indexLists[0].values.length).toEqual(8 * 3); + expect(m.indexList.values.length).toEqual(8 * 3); }); it('compute positions with rotation', function() { @@ -66,7 +66,7 @@ defineSuite([ var length = positions.length; expect(length).toEqual(9 * 3); - expect(m.indexLists[0].values.length).toEqual(8 * 3); + expect(m.indexList.values.length).toEqual(8 * 3); var unrotatedSECorner = extent.getSoutheast(); var projection = new GeographicProjection(); @@ -89,7 +89,7 @@ defineSuite([ var length = positions.length; expect(length).toEqual(9 * 3); - expect(m.indexLists[0].values.length).toEqual(8 * 3); + expect(m.indexList.values.length).toEqual(8 * 3); var unrotatedNWCorner = Ellipsoid.WGS84.cartographicToCartesian(extent.getNorthwest()); var unrotatedSECorner = Ellipsoid.WGS84.cartographicToCartesian(extent.getSoutheast()); diff --git a/Specs/Core/GeometryFiltersSpec.js b/Specs/Core/GeometryFiltersSpec.js index 6efaab9037a6..da5b11f6a3ef 100644 --- a/Specs/Core/GeometryFiltersSpec.js +++ b/Specs/Core/GeometryFiltersSpec.js @@ -36,15 +36,15 @@ defineSuite([ it('converts triangles to wireframe in place', function() { var mesh = GeometryFilters.toWireframe({ - indexLists : [{ + indexList : { primitiveType : PrimitiveType.TRIANGLES, values : [0, 1, 2, 3, 4, 5] - }] + } }); - expect(mesh.indexLists[0].primitiveType).toEqual(PrimitiveType.LINES); + expect(mesh.indexList.primitiveType).toEqual(PrimitiveType.LINES); - var v = mesh.indexLists[0].values; + var v = mesh.indexList.values; expect(v.length).toEqual(12); expect(v[0]).toEqual(0); @@ -64,15 +64,15 @@ defineSuite([ it('converts a triangle fan to wireframe in place', function() { var mesh = GeometryFilters.toWireframe({ - indexLists : [{ + indexList : { primitiveType : PrimitiveType.TRIANGLE_FAN, values : [0, 1, 2, 3] - }] + } }); - expect(mesh.indexLists[0].primitiveType).toEqual(PrimitiveType.LINES); + expect(mesh.indexList.primitiveType).toEqual(PrimitiveType.LINES); - var v = mesh.indexLists[0].values; + var v = mesh.indexList.values; expect(v.length).toEqual(12); expect(v[0]).toEqual(0); @@ -92,15 +92,15 @@ defineSuite([ it('converts a triangle strip to wireframe in place', function() { var mesh = GeometryFilters.toWireframe({ - indexLists : [{ + indexList : { primitiveType : PrimitiveType.TRIANGLE_STRIP, values : [0, 1, 2, 3] - }] + } }); - expect(mesh.indexLists[0].primitiveType).toEqual(PrimitiveType.LINES); + expect(mesh.indexList.primitiveType).toEqual(PrimitiveType.LINES); - var v = mesh.indexLists[0].values; + var v = mesh.indexList.values; expect(v.length).toEqual(12); expect(v[0]).toEqual(0); @@ -178,17 +178,11 @@ defineSuite([ it('can reorder all indices and attributes for the pre vertex cahce', function() { var mesh = {}; mesh.attributes = {}; - mesh.indexLists = []; - mesh.indexLists.push({ + mesh.indexList = { primitiveType : PrimitiveType.TRIANGLES, - values : [5, 3, 2, 0, 1, 4] - }); - - mesh.indexLists.push({ - primitiveType : PrimitiveType.TRIANGLES, - values : [4, 1, 3, 2, 5, 0] - }); + values : [5, 3, 2, 0, 1, 4, 4, 1, 3, 2, 5, 0] + }; mesh.attributes.vertexNames = { componentDatatype : ComponentDatatype.FLOAT, @@ -203,19 +197,18 @@ defineSuite([ }; GeometryFilters.reorderForPreVertexCache(mesh); - expect(mesh.indexLists[0].values[0]).toEqual(0); - expect(mesh.indexLists[0].values[1]).toEqual(1); - expect(mesh.indexLists[0].values[2]).toEqual(2); - expect(mesh.indexLists[0].values[3]).toEqual(3); - expect(mesh.indexLists[0].values[4]).toEqual(4); - expect(mesh.indexLists[0].values[5]).toEqual(5); - - expect(mesh.indexLists[1].values[0]).toEqual(5); - expect(mesh.indexLists[1].values[1]).toEqual(4); - expect(mesh.indexLists[1].values[2]).toEqual(1); - expect(mesh.indexLists[1].values[3]).toEqual(2); - expect(mesh.indexLists[1].values[4]).toEqual(0); - expect(mesh.indexLists[1].values[5]).toEqual(3); + expect(mesh.indexList.values[0]).toEqual(0); + expect(mesh.indexList.values[1]).toEqual(1); + expect(mesh.indexList.values[2]).toEqual(2); + expect(mesh.indexList.values[3]).toEqual(3); + expect(mesh.indexList.values[4]).toEqual(4); + expect(mesh.indexList.values[5]).toEqual(5); + expect(mesh.indexList.values[6]).toEqual(5); + expect(mesh.indexList.values[7]).toEqual(4); + expect(mesh.indexList.values[8]).toEqual(1); + expect(mesh.indexList.values[9]).toEqual(2); + expect(mesh.indexList.values[10]).toEqual(0); + expect(mesh.indexList.values[11]).toEqual(3); expect(mesh.attributes.vertexNames.values[0]).toEqual('v5'); expect(mesh.attributes.vertexNames.values[1]).toEqual('v3'); @@ -249,7 +242,7 @@ defineSuite([ ellipsoid : new Ellipsoid(10.0, 10.0, 10.0), numberOfPartitions : 100 }); - var indices = mesh.indexLists[0].values; + var indices = mesh.indexList.values; var numIndices = indices.length; var maximumIndex = 0; for ( var i = 0; i < numIndices; i++) { @@ -262,7 +255,7 @@ defineSuite([ cacheSize : 24}); expect(ACMRbefore).toBeGreaterThan(1.00); mesh = GeometryFilters.reorderForPostVertexCache(mesh); - indices = mesh.indexLists[0].values; + indices = mesh.indexList.values; var ACMRafter = Tipsify.calculateACMR({indices : indices, maximumIndex : maximumIndex, cacheSize : 24}); @@ -283,10 +276,10 @@ defineSuite([ values : [1.0] } }, - indexLists : [{ + indexList : { primitiveType : PrimitiveType.TRIANGLES, values : [0, 0, 0] - }] + } }; var meshes = GeometryFilters.fitToUnsignedShortIndices(mesh); @@ -310,10 +303,10 @@ defineSuite([ values : times } }, - indexLists : [{ + indexList : { primitiveType : PrimitiveType.TRIANGLES, values : [0, 0, 0, sixtyFourK, sixtyFourK, sixtyFourK, 0, sixtyFourK, 0] - }] + } }; var meshes = GeometryFilters.fitToUnsignedShortIndices(mesh); @@ -323,8 +316,8 @@ defineSuite([ expect(meshes[0].attributes.time.componentsPerAttribute).toEqual(1); expect(meshes[0].attributes.time.values).toEqual([0, sixtyFourK]); - expect(meshes[0].indexLists[0].primitiveType).toEqual(PrimitiveType.TRIANGLES); - expect(meshes[0].indexLists[0].values).toEqual([0, 0, 0, 1, 1, 1, 0, 1, 0]); + expect(meshes[0].indexList.primitiveType).toEqual(PrimitiveType.TRIANGLES); + expect(meshes[0].indexList.values).toEqual([0, 0, 0, 1, 1, 1, 0, 1, 0]); }); it('fitToUnsignedShortIndices creates two meshes', function() { @@ -349,10 +342,10 @@ defineSuite([ values : positions } }, - indexLists : [{ + indexList : { primitiveType : PrimitiveType.TRIANGLES, values : indices - }] + } }; var meshes = GeometryFilters.fitToUnsignedShortIndices(mesh); @@ -360,10 +353,10 @@ defineSuite([ expect(meshes.length).toEqual(2); expect(meshes[0].attributes.position.values.length).toEqual(positions.length - 6); // Two vertices are not copied (0, 1) - expect(meshes[0].indexLists[0].values.length).toEqual(indices.length - 3); // One triangle is not copied (0, 1, 2) + expect(meshes[0].indexList.values.length).toEqual(indices.length - 3); // One triangle is not copied (0, 1, 2) expect(meshes[1].attributes.position.values.length).toEqual(9); - expect(meshes[1].indexLists[0].values.length).toEqual(3); + expect(meshes[1].indexList.values.length).toEqual(3); }); it('fitToUnsignedShortIndices throws without triangles', function() { @@ -376,10 +369,10 @@ defineSuite([ } }, - indexLists : [{ + indexList : { primitiveType : PrimitiveType.POINTS, values : [0] - }] + } }; expect(function() { @@ -403,10 +396,10 @@ defineSuite([ } }, - indexLists : [{ + indexList : { primitiveType : PrimitiveType.TRIANGLES, values : [0, 0, 0] - }] + } }; expect(function() { @@ -547,13 +540,10 @@ defineSuite([ ] }) }, - indexLists : [new GeometryIndices({ + indexList : new GeometryIndices({ primitiveType : PrimitiveType.TRIANGLES, values : [0, 1, 2] - }), new GeometryIndices({ - primitiveType : PrimitiveType.LINES, - values : [1, 2] - })] + }) }) }); var anotherInstance = new GeometryInstance({ @@ -569,13 +559,10 @@ defineSuite([ ] }) }, - indexLists : [new GeometryIndices({ + indexList : new GeometryIndices({ primitiveType : PrimitiveType.TRIANGLES, values : [0, 1, 2] - }), new GeometryIndices({ - primitiveType : PrimitiveType.POINTS, - values : [0, 1, 2] - })] + }) }) }); @@ -595,16 +582,10 @@ defineSuite([ ]) }) }, - indexLists : [new GeometryIndices({ + indexList : new GeometryIndices({ primitiveType : PrimitiveType.TRIANGLES, values : new Uint16Array([0, 1, 2, 3, 4, 5]) - }), new GeometryIndices({ - primitiveType : PrimitiveType.LINES, - values : new Uint16Array([1, 2]) - }), new GeometryIndices({ - primitiveType : PrimitiveType.POINTS, - values : new Uint16Array([3, 4, 5]) - })] + }) })); }); @@ -676,7 +657,7 @@ defineSuite([ }).toThrow(); }); - it('GeometryFilters.computeNormal does not compute normals when mesh.indexLists is undefined', function() { + it('GeometryFilters.computeNormal does not compute normals when mesh.indexList is undefined', function() { var mesh = new Geometry({ attributes: { position: { @@ -704,10 +685,10 @@ defineSuite([ } }, - indexLists: [{ + indexList : { primitiveType: PrimitiveType.TRIANGLE_STRIP, values: [0, 1, 2] - }] + } }); mesh = GeometryFilters.computeNormal(mesh); @@ -726,10 +707,10 @@ defineSuite([ componentsPerAttribute: 3 } }, - indexLists: [{ + indexList : { primitiveType: PrimitiveType.TRIANGLES, values: [0, 1, 2] - }] + } }); mesh = GeometryFilters.computeNormal(mesh); @@ -749,10 +730,10 @@ defineSuite([ componentsPerAttribute: 3 } }, - indexLists: [{ + indexList : { primitiveType: PrimitiveType.TRIANGLES, values: [0, 1, 2, 1, 3, 2] - }] + } }); mesh = GeometryFilters.computeNormal(mesh); @@ -779,10 +760,10 @@ defineSuite([ componentsPerAttribute: 3 } }, - indexLists: [{ + indexList : { primitiveType: PrimitiveType.TRIANGLES, values: [0, 1, 2, 3, 0, 2, 4, 0, 3, 4, 5, 0, 5, 6, 0, 6, 1, 0] - }] + } }); mesh = GeometryFilters.computeNormal(mesh); @@ -1026,7 +1007,7 @@ defineSuite([ }); - it('GeometryFilters.computeTangentAndBinormal does not compute tangent and binormals when mesh.indexLists is undefined', function() { + it('GeometryFilters.computeTangentAndBinormal does not compute tangent and binormals when mesh.indexList is undefined', function() { var mesh = new Geometry({ attributes: { position: { @@ -1078,10 +1059,10 @@ defineSuite([ componentsPerAttribute: 2 } }, - indexLists: [{ + indexList : { primitiveType: PrimitiveType.TRIANGLE_STRIP, values: [0, 1, 2] - }] + } }); mesh = GeometryFilters.computeTangentAndBinormal(mesh); @@ -1106,10 +1087,10 @@ defineSuite([ componentsPerAttribute: 2 } }, - indexLists: [{ + indexList : { primitiveType: PrimitiveType.TRIANGLES, values: [0, 1, 2] - }] + } }); mesh = GeometryFilters.computeNormal(mesh); @@ -1137,10 +1118,10 @@ defineSuite([ componentsPerAttribute: 2 } }, - indexLists: [{ + indexList : { primitiveType: PrimitiveType.TRIANGLES, values: [0, 1, 2, 1, 3, 2] - }] + } }); mesh = GeometryFilters.computeNormal(mesh); diff --git a/Specs/Core/PolygonGeometrySpec.js b/Specs/Core/PolygonGeometrySpec.js index d14eb652411a..a43c1a608031 100644 --- a/Specs/Core/PolygonGeometrySpec.js +++ b/Specs/Core/PolygonGeometrySpec.js @@ -93,7 +93,7 @@ defineSuite([ }); expect(p.attributes.position.values.length).toEqual(3 * 11); - expect(p.indexLists[0].values.length).toEqual(3 * 14); + expect(p.indexList.values.length).toEqual(3 * 14); }); it('computes all attributes', function() { @@ -113,7 +113,7 @@ defineSuite([ expect(p.attributes.normal.values.length).toEqual(3 * 11); expect(p.attributes.tangent.values.length).toEqual(3 * 11); expect(p.attributes.binormal.values.length).toEqual(3 * 11); - expect(p.indexLists[0].values.length).toEqual(3 * 14); + expect(p.indexList.values.length).toEqual(3 * 14); }); it('creates a polygon from hierarchy', function() { @@ -149,7 +149,7 @@ defineSuite([ }); expect(p.attributes.position.values.length).toEqual(3 * 14); - expect(p.indexLists[0].values.length).toEqual(3 * 10); + expect(p.indexList.values.length).toEqual(3 * 10); }); it('creates a polygon from clockwise hierarchy', function() { @@ -185,7 +185,7 @@ defineSuite([ }); expect(p.attributes.position.values.length).toEqual(3 * 14); - expect(p.indexLists[0].values.length).toEqual(3 * 10); + expect(p.indexList.values.length).toEqual(3 * 10); }); }, 'WebGL'); diff --git a/Specs/Core/PolygonPipelineSpec.js b/Specs/Core/PolygonPipelineSpec.js index a8f975cca16b..0951b0fbcd0f 100644 --- a/Specs/Core/PolygonPipelineSpec.js +++ b/Specs/Core/PolygonPipelineSpec.js @@ -360,9 +360,9 @@ defineSuite([ expect(subdivision.attributes.position.values[7]).toEqual(0.0); expect(subdivision.attributes.position.values[8]).toEqual(0.0); - expect(subdivision.indexLists[0].values[0]).toEqual(0); - expect(subdivision.indexLists[0].values[1]).toEqual(1); - expect(subdivision.indexLists[0].values[2]).toEqual(2); + expect(subdivision.indexList.values[0]).toEqual(0); + expect(subdivision.indexList.values[1]).toEqual(1); + expect(subdivision.indexList.values[2]).toEqual(2); }); it('eliminateHoles throws an exception without an outerRing', function() { diff --git a/Specs/Core/WallGeometrySpec.js b/Specs/Core/WallGeometrySpec.js index 637599f1d889..70197b6d10cc 100644 --- a/Specs/Core/WallGeometrySpec.js +++ b/Specs/Core/WallGeometrySpec.js @@ -42,7 +42,7 @@ defineSuite([ }); expect(w.attributes.position.values.length).toEqual(2 * 2 * 3); - expect(w.indexLists[0].values.length).toEqual(2 * 3); + expect(w.indexList.values.length).toEqual(2 * 3); }); it('creates positions relative to terrain', function() { @@ -63,7 +63,7 @@ defineSuite([ }); expect(w.attributes.position.values.length).toEqual(2 * 2 * 3); - expect(w.indexLists[0].values.length).toEqual(2 * 3); + expect(w.indexList.values.length).toEqual(2 * 3); }); it('creates all attributes', function() { @@ -83,7 +83,7 @@ defineSuite([ expect(w.attributes.tangent.values.length).toEqual(3 * 2 * 3); expect(w.attributes.binormal.values.length).toEqual(3 * 2 * 3); expect(w.attributes.st.values.length).toEqual(3 * 2 * 2); - expect(w.indexLists[0].values.length).toEqual((3 * 2 - 2) * 3); + expect(w.indexList.values.length).toEqual((3 * 2 - 2) * 3); }); }); diff --git a/Specs/Renderer/VertexArrayFactorySpec.js b/Specs/Renderer/VertexArrayFactorySpec.js index 3dd14d9f3186..0763859acc96 100644 --- a/Specs/Renderer/VertexArrayFactorySpec.js +++ b/Specs/Renderer/VertexArrayFactorySpec.js @@ -541,10 +541,10 @@ defineSuite([ it('creates an index buffer', function() { var mesh = { - indexLists : [{ + indexList : { primitiveType : PrimitiveType.POINTS, values : [0] - }] + } }; var va = context.createVertexArrayFromMesh({ @@ -555,25 +555,7 @@ defineSuite([ expect(va.getIndexBuffer()).toBeDefined(); expect(va.getIndexBuffer().getUsage()).toEqual(BufferUsage.DYNAMIC_DRAW); // Default expect(va.getIndexBuffer().getIndexDatatype()).toEqual(IndexDatatype.UNSIGNED_SHORT); - expect(va.getIndexBuffer().getNumberOfIndices()).toEqual(mesh.indexLists[0].values.length); - }); - - it('throws with multiple index lists', function() { - var mesh = { - indexLists : [{ - primitiveType : PrimitiveType.POINTS, - values : [0] - }, { - primitiveType : PrimitiveType.POINTS, - values : [1] - }] - }; - - expect(function() { - return context.createVertexArrayFromMesh({ - mesh : mesh - }); - }).toThrow(); + expect(va.getIndexBuffer().getNumberOfIndices()).toEqual(mesh.indexList.values.length); }); it('throws with different number of interleaved attributes', function() { From dc6180660966fda4aa8c477972683801e22613c5 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Wed, 5 Jun 2013 11:35:55 -0400 Subject: [PATCH 141/306] Moved PrimitiveType to Geometry --- Source/Core/BoxGeometry.js | 7 ++- Source/Core/CircleGeometry.js | 5 ++ Source/Core/EllipseGeometry.js | 6 ++- Source/Core/EllipsoidGeometry.js | 6 ++- Source/Core/ExtentGeometry.js | 6 ++- Source/Core/Geometry.js | 6 +++ Source/Core/GeometryFilters.js | 37 +++++++------- Source/Core/GeometryIndices.js | 7 --- Source/Core/PolygonGeometry.js | 5 ++ Source/Core/PolygonPipeline.js | 5 +- Source/Core/WallGeometry.js | 6 ++- Source/Scene/CentralBody.js | 4 +- Source/Scene/ImageryLayer.js | 4 +- Source/Scene/Primitive.js | 5 +- Specs/Core/GeometryFiltersSpec.js | 85 +++++++++++++++---------------- 15 files changed, 110 insertions(+), 84 deletions(-) diff --git a/Source/Core/BoxGeometry.js b/Source/Core/BoxGeometry.js index 5fd6be06be6a..368a0216f698 100644 --- a/Source/Core/BoxGeometry.js +++ b/Source/Core/BoxGeometry.js @@ -294,7 +294,6 @@ define([ indexList = new GeometryIndices({ // 12 triangles: 6 faces, 2 triangles each. - primitiveType : PrimitiveType.TRIANGLES, values : [ // +z face 0, 1, 2, @@ -341,7 +340,6 @@ define([ indexList = new GeometryIndices({ // 12 triangles: 6 faces, 2 triangles each. - primitiveType : PrimitiveType.TRIANGLES, values : [ 4, 5, 6, // plane z = corner.Z 4, 6, 7, @@ -374,6 +372,11 @@ define([ */ this.indexList = indexList; + /** + * DOC_TBA + */ + this.primitiveType = PrimitiveType.TRIANGLES; + /** * A tight-fitting bounding sphere that encloses the vertices of the geometry. * diff --git a/Source/Core/CircleGeometry.js b/Source/Core/CircleGeometry.js index 8023fe1077f6..aa9f8e6f5b42 100644 --- a/Source/Core/CircleGeometry.js +++ b/Source/Core/CircleGeometry.js @@ -72,6 +72,11 @@ define([ */ this.indexList = ellipseGeometry.indexList; + /** + * DOC_TBA + */ + this.primitiveType = ellipseGeometry.primitiveType; + /** * A tight-fitting bounding sphere that encloses the vertices of the geometry. * diff --git a/Source/Core/EllipseGeometry.js b/Source/Core/EllipseGeometry.js index 7e050f002e61..523cf2913bac 100644 --- a/Source/Core/EllipseGeometry.js +++ b/Source/Core/EllipseGeometry.js @@ -437,10 +437,14 @@ define([ * @type GeometryIndices */ this.indexList = new GeometryIndices({ - primitiveType : PrimitiveType.TRIANGLES, values : indices }); + /** + * DOC_TBA + */ + this.primitiveType = PrimitiveType.TRIANGLES; + /** * A tight-fitting bounding sphere that encloses the vertices of the geometry. * diff --git a/Source/Core/EllipsoidGeometry.js b/Source/Core/EllipsoidGeometry.js index 2b59ad0e0919..efec94de3e6b 100644 --- a/Source/Core/EllipsoidGeometry.js +++ b/Source/Core/EllipsoidGeometry.js @@ -321,10 +321,14 @@ define([ * @type GeometryIndices */ this.indexList = new GeometryIndices({ - primitiveType : PrimitiveType.TRIANGLES, values : indices }); + /** + * DOC_TBA + */ + this.primitiveType = PrimitiveType.TRIANGLES; + /** * A tight-fitting bounding sphere that encloses the vertices of the geometry. * diff --git a/Source/Core/ExtentGeometry.js b/Source/Core/ExtentGeometry.js index 751a1af63083..aff632557085 100644 --- a/Source/Core/ExtentGeometry.js +++ b/Source/Core/ExtentGeometry.js @@ -309,10 +309,14 @@ define([ * @type GeometryIndices */ this.indexList = new GeometryIndices({ - primitiveType : PrimitiveType.TRIANGLES, values : indices }); + /** + * DOC_TBA + */ + this.primitiveType = PrimitiveType.TRIANGLES; + /** * A tight-fitting bounding sphere that encloses the vertices of the geometry. * diff --git a/Source/Core/Geometry.js b/Source/Core/Geometry.js index 880069948b61..d5e86d60797e 100644 --- a/Source/Core/Geometry.js +++ b/Source/Core/Geometry.js @@ -26,6 +26,11 @@ define([ */ this.indexList = options.indexList; + /** + * DOC_TBA + */ + this.primitiveType = options.primitiveType; + /** * DOC_TBA */ @@ -51,6 +56,7 @@ define([ result.attributes = newAttributes; result.indexList = (typeof this.indexList !== 'undefined') ? this.indexList.clone() : undefined; + result.primitiveType = this.primitiveType; this.boundingSphere.clone(result.boundingSphere); return result; diff --git a/Source/Core/GeometryFilters.js b/Source/Core/GeometryFilters.js index 0cc15420c496..ee3843bbd2ad 100644 --- a/Source/Core/GeometryFilters.js +++ b/Source/Core/GeometryFilters.js @@ -113,7 +113,7 @@ define([ if (typeof mesh !== 'undefined') { var indices = mesh.indexList; if (typeof indices !== 'undefined') { - switch (indices.primitiveType) { + switch (mesh.primitiveType) { case PrimitiveType.TRIANGLES: indices.values = trianglesToLines(indices.values); break; @@ -125,7 +125,7 @@ define([ break; } - indices.primitiveType = PrimitiveType.LINES; + mesh.primitiveType = PrimitiveType.LINES; } } @@ -330,28 +330,26 @@ define([ /** * DOC_TBA. Old mesh is not guaranteed to be copied. * - * @exception {DeveloperError} The mesh's index-lists must have PrimitiveType equal to PrimitiveType.TRIANGLES. + * @exception {DeveloperError} mesh.primitiveType must equal to PrimitiveType.TRIANGLES. * @exception {DeveloperError} All mesh attribute lists must have the same number of attributes. */ GeometryFilters.fitToUnsignedShortIndices = function(mesh) { function createMesh(attributes, primitiveType, indices) { + // TODO: is this always what we want, for say BoxGeometry? return new Geometry({ attributes : attributes, indexList : new GeometryIndices({ - primitiveType : primitiveType, values : indices }), - boundingSphere : (typeof mesh.boundingSphere !== 'undefined') ? BoundingSphere.clone(mesh.boundingSphere) : undefined, - modelMatrix : (typeof mesh.modelMatrix !== 'undefined') ? Matrix4.clone(mesh.modelMatrix) : undefined, - pickData : mesh.pickData + primitiveType : primitiveType }); } var meshes = []; if (typeof mesh !== 'undefined') { - if (mesh.indexList.primitiveType !== PrimitiveType.TRIANGLES) { - throw new DeveloperError('indexList must have PrimitiveType equal to PrimitiveType.TRIANGLES.'); + if (mesh.primitiveType !== PrimitiveType.TRIANGLES) { + throw new DeveloperError('mesh.primitiveType must equal to PrimitiveType.TRIANGLES.'); } var numberOfVertices = Geometry.computeNumberOfVertices(mesh); @@ -404,7 +402,7 @@ define([ newIndices.push(i2); if (currentIndex + 3 > sixtyFourK) { - meshes.push(createMesh(newAttributes, mesh.indexList.primitiveType, newIndices)); + meshes.push(createMesh(newAttributes, mesh.primitiveType, newIndices)); // Reset for next vertex-array oldToNewIndex = []; @@ -415,7 +413,7 @@ define([ } if (newIndices.length !== 0) { - meshes.push(createMesh(newAttributes, mesh.indexList.primitiveType, newIndices)); + meshes.push(createMesh(newAttributes, mesh.primitiveType, newIndices)); } } else { // No need to split into multiple meshes @@ -717,13 +715,14 @@ define([ // Combine index lists // First, determine the size of a typed array per primitive type + var primitiveType = instances[0].geometry.primitiveType; var numberOfIndices = {}; var indices; for (i = 0; i < length; ++i) { indices = instances[i].geometry.indexList; - numberOfIndices[indices.primitiveType] = (typeof numberOfIndices[indices.primitiveType] !== 'undefined') ? - (numberOfIndices[indices.primitiveType] += indices.values.length) : indices.values.length; + numberOfIndices[primitiveType] = (typeof numberOfIndices[primitiveType] !== 'undefined') ? + (numberOfIndices[primitiveType] += indices.values.length) : indices.values.length; } // Next, allocate a typed array for indices per primitive type @@ -742,7 +741,6 @@ define([ } combinedIndexLists.push(new GeometryIndices({ - primitiveType : PrimitiveType[name], values : values })); @@ -760,14 +758,14 @@ define([ indices = instances[i].geometry.indexList; sourceValues = indices.values; sourceValuesLength = sourceValues.length; - var destValues = indexListsByPrimitiveType[indices.primitiveType].values; - var n = indexListsByPrimitiveType[indices.primitiveType].currentOffset; + var destValues = indexListsByPrimitiveType[primitiveType].values; + var n = indexListsByPrimitiveType[primitiveType].currentOffset; for (k = 0; k < sourceValuesLength; ++k) { destValues[n++] = offset + sourceValues[k]; } - indexListsByPrimitiveType[indices.primitiveType].currentOffset = n; + indexListsByPrimitiveType[primitiveType].currentOffset = n; var attrs = instances[i].geometry.attributes; for (name in attrs) { @@ -800,6 +798,7 @@ define([ attributes : attributes, // TODO: cleanup combinedIndexLists indexList : combinedIndexLists[0], + primitiveType : primitiveType, boundingSphere : boundingSphere }); }; @@ -843,7 +842,7 @@ define([ } var indices = indexList.values; - if (indexList.primitiveType !== PrimitiveType.TRIANGLES || typeof indices === 'undefined' || + if (mesh.primitiveType !== PrimitiveType.TRIANGLES || typeof indices === 'undefined' || indices.length < 2 || indices.length % 3 !== 0) { return mesh; } @@ -1008,7 +1007,7 @@ define([ } var indices = indexList.values; - if (indexList.primitiveType !== PrimitiveType.TRIANGLES || typeof indices === 'undefined' || + if (geometry.primitiveType !== PrimitiveType.TRIANGLES || typeof indices === 'undefined' || indices.length < 2 || indices.length % 3 !== 0) { return geometry; } diff --git a/Source/Core/GeometryIndices.js b/Source/Core/GeometryIndices.js index 505e86093292..cd61b57c290d 100644 --- a/Source/Core/GeometryIndices.js +++ b/Source/Core/GeometryIndices.js @@ -14,11 +14,6 @@ define([ var GeometryIndices = function(options) { options = defaultValue(options, defaultValue.EMPTY_OBJECT); - /** - * DOC_TBA - */ - this.primitiveType = options.primitiveType; - /** * DOC_TBA */ @@ -33,8 +28,6 @@ define([ result = new GeometryIndices(); } - result.primitiveType = this.primitiveType; // Shallow copy enum - // TODO: typed array or not. fastest way to copy? var sourceValues = this.values; var length = sourceValues.length; diff --git a/Source/Core/PolygonGeometry.js b/Source/Core/PolygonGeometry.js index ae0ef83a79ef..255293845bb6 100644 --- a/Source/Core/PolygonGeometry.js +++ b/Source/Core/PolygonGeometry.js @@ -421,6 +421,11 @@ define([ */ this.indexList = mesh.indexList; + /** + * DOC_TBA + */ + this.primitiveType = mesh.primitiveType; + /** * A tight-fitting bounding sphere that encloses the vertices of the geometry. * diff --git a/Source/Core/PolygonPipeline.js b/Source/Core/PolygonPipeline.js index f6aaeda89f0f..e90964a5d237 100644 --- a/Source/Core/PolygonPipeline.js +++ b/Source/Core/PolygonPipeline.js @@ -839,9 +839,10 @@ define([ }, indexList : new GeometryIndices({ - primitiveType : PrimitiveType.TRIANGLES, values : subdividedIndices - }) + }), + + primitiveType : PrimitiveType.TRIANGLES }); }, diff --git a/Source/Core/WallGeometry.js b/Source/Core/WallGeometry.js index 98257a0719a3..087f8eb6932f 100644 --- a/Source/Core/WallGeometry.js +++ b/Source/Core/WallGeometry.js @@ -289,10 +289,14 @@ define([ * @type GeometryIndices */ this.indexList = new GeometryIndices({ - primitiveType : PrimitiveType.TRIANGLES, values : indices }); + /** + * DOC_TBA + */ + this.primitiveType = PrimitiveType.TRIANGLES; + /** * A tight-fitting bounding sphere that encloses the vertices of the geometry. * diff --git a/Source/Scene/CentralBody.js b/Source/Scene/CentralBody.js index 493e5d19574e..18cf4f93920b 100644 --- a/Source/Scene/CentralBody.js +++ b/Source/Scene/CentralBody.js @@ -550,9 +550,9 @@ define([ } }, indexList : { - primitiveType : PrimitiveType.TRIANGLES, values : [0, 1, 2, 2, 1, 3] - } + }, + primitiveType : PrimitiveType.TRIANGLES }; this._depthCommand.vertexArray = context.createVertexArrayFromMesh({ mesh : mesh, diff --git a/Source/Scene/ImageryLayer.js b/Source/Scene/ImageryLayer.js index 132d944039e0..0e7eebabb122 100644 --- a/Source/Scene/ImageryLayer.js +++ b/Source/Scene/ImageryLayer.js @@ -804,9 +804,9 @@ define([ } }, indexList : { - primitiveType : PrimitiveType.TRIANGLES, values : TerrainProvider.getRegularGridIndices(256, 256) - } + }, + primitiveType : PrimitiveType.TRIANGLES }; var reprojectAttribInds = { diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index 418ad15d142b..d87bfe915f2f 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -399,8 +399,7 @@ define([ var geometry = geometries[i]; var command = new DrawCommand(); -// TODO: this assumes indices in the geometries - command.primitiveType = geometry.indexList.primitiveType; + command.primitiveType = geometry.primitiveType; command.vertexArray = this._va[i]; command.renderState = rs; command.shaderProgram = this._sp; @@ -409,7 +408,7 @@ define([ colorCommands.push(command); var pickCommand = new DrawCommand(); - pickCommand.primitiveType = geometry.indexList.primitiveType; + pickCommand.primitiveType = geometry.primitiveType; pickCommand.vertexArray = this._va[i]; pickCommand.renderState = pickRS; pickCommand.shaderProgram = this._pickSP; diff --git a/Specs/Core/GeometryFiltersSpec.js b/Specs/Core/GeometryFiltersSpec.js index da5b11f6a3ef..6dbe72b32a4d 100644 --- a/Specs/Core/GeometryFiltersSpec.js +++ b/Specs/Core/GeometryFiltersSpec.js @@ -37,12 +37,12 @@ defineSuite([ it('converts triangles to wireframe in place', function() { var mesh = GeometryFilters.toWireframe({ indexList : { - primitiveType : PrimitiveType.TRIANGLES, values : [0, 1, 2, 3, 4, 5] - } + }, + primitiveType : PrimitiveType.TRIANGLES }); - expect(mesh.indexList.primitiveType).toEqual(PrimitiveType.LINES); + expect(mesh.primitiveType).toEqual(PrimitiveType.LINES); var v = mesh.indexList.values; expect(v.length).toEqual(12); @@ -65,12 +65,12 @@ defineSuite([ it('converts a triangle fan to wireframe in place', function() { var mesh = GeometryFilters.toWireframe({ indexList : { - primitiveType : PrimitiveType.TRIANGLE_FAN, values : [0, 1, 2, 3] - } + }, + primitiveType : PrimitiveType.TRIANGLE_FAN }); - expect(mesh.indexList.primitiveType).toEqual(PrimitiveType.LINES); + expect(mesh.primitiveType).toEqual(PrimitiveType.LINES); var v = mesh.indexList.values; expect(v.length).toEqual(12); @@ -93,12 +93,12 @@ defineSuite([ it('converts a triangle strip to wireframe in place', function() { var mesh = GeometryFilters.toWireframe({ indexList : { - primitiveType : PrimitiveType.TRIANGLE_STRIP, values : [0, 1, 2, 3] - } + }, + primitiveType : PrimitiveType.TRIANGLE_STRIP }); - expect(mesh.indexList.primitiveType).toEqual(PrimitiveType.LINES); + expect(mesh.primitiveType).toEqual(PrimitiveType.LINES); var v = mesh.indexList.values; expect(v.length).toEqual(12); @@ -180,10 +180,11 @@ defineSuite([ mesh.attributes = {}; mesh.indexList = { - primitiveType : PrimitiveType.TRIANGLES, values : [5, 3, 2, 0, 1, 4, 4, 1, 3, 2, 5, 0] }; + mesh.primitiveType = PrimitiveType.TRIANGLES; + mesh.attributes.vertexNames = { componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 1, @@ -277,9 +278,9 @@ defineSuite([ } }, indexList : { - primitiveType : PrimitiveType.TRIANGLES, values : [0, 0, 0] - } + }, + primitiveType : PrimitiveType.TRIANGLES }; var meshes = GeometryFilters.fitToUnsignedShortIndices(mesh); @@ -304,9 +305,9 @@ defineSuite([ } }, indexList : { - primitiveType : PrimitiveType.TRIANGLES, values : [0, 0, 0, sixtyFourK, sixtyFourK, sixtyFourK, 0, sixtyFourK, 0] - } + }, + primitiveType : PrimitiveType.TRIANGLES }; var meshes = GeometryFilters.fitToUnsignedShortIndices(mesh); @@ -316,7 +317,7 @@ defineSuite([ expect(meshes[0].attributes.time.componentsPerAttribute).toEqual(1); expect(meshes[0].attributes.time.values).toEqual([0, sixtyFourK]); - expect(meshes[0].indexList.primitiveType).toEqual(PrimitiveType.TRIANGLES); + expect(meshes[0].primitiveType).toEqual(PrimitiveType.TRIANGLES); expect(meshes[0].indexList.values).toEqual([0, 0, 0, 1, 1, 1, 0, 1, 0]); }); @@ -343,9 +344,9 @@ defineSuite([ } }, indexList : { - primitiveType : PrimitiveType.TRIANGLES, values : indices - } + }, + primitiveType : PrimitiveType.TRIANGLES }; var meshes = GeometryFilters.fitToUnsignedShortIndices(mesh); @@ -368,11 +369,10 @@ defineSuite([ values : [10.0] } }, - indexList : { - primitiveType : PrimitiveType.POINTS, values : [0] - } + }, + primitiveType : PrimitiveType.POINTS }; expect(function() { @@ -395,11 +395,10 @@ defineSuite([ values : [1.0, 2.0] } }, - indexList : { - primitiveType : PrimitiveType.TRIANGLES, values : [0, 0, 0] - } + }, + primitiveType : PrimitiveType.TRIANGLES }; expect(function() { @@ -541,9 +540,9 @@ defineSuite([ }) }, indexList : new GeometryIndices({ - primitiveType : PrimitiveType.TRIANGLES, values : [0, 1, 2] - }) + }), + primitiveType : PrimitiveType.TRIANGLES }) }); var anotherInstance = new GeometryInstance({ @@ -560,9 +559,9 @@ defineSuite([ }) }, indexList : new GeometryIndices({ - primitiveType : PrimitiveType.TRIANGLES, values : [0, 1, 2] - }) + }), + primitiveType : PrimitiveType.TRIANGLES }) }); @@ -583,9 +582,9 @@ defineSuite([ }) }, indexList : new GeometryIndices({ - primitiveType : PrimitiveType.TRIANGLES, values : new Uint16Array([0, 1, 2, 3, 4, 5]) - }) + }), + primitiveType : PrimitiveType.TRIANGLES })); }); @@ -686,9 +685,9 @@ defineSuite([ } }, indexList : { - primitiveType: PrimitiveType.TRIANGLE_STRIP, values: [0, 1, 2] - } + }, + primitiveType: PrimitiveType.TRIANGLE_STRIP }); mesh = GeometryFilters.computeNormal(mesh); @@ -708,9 +707,9 @@ defineSuite([ } }, indexList : { - primitiveType: PrimitiveType.TRIANGLES, values: [0, 1, 2] - } + }, + primitiveType: PrimitiveType.TRIANGLES }); mesh = GeometryFilters.computeNormal(mesh); @@ -731,9 +730,9 @@ defineSuite([ } }, indexList : { - primitiveType: PrimitiveType.TRIANGLES, values: [0, 1, 2, 1, 3, 2] - } + }, + primitiveType: PrimitiveType.TRIANGLES }); mesh = GeometryFilters.computeNormal(mesh); @@ -761,9 +760,9 @@ defineSuite([ } }, indexList : { - primitiveType: PrimitiveType.TRIANGLES, values: [0, 1, 2, 3, 0, 2, 4, 0, 3, 4, 5, 0, 5, 6, 0, 6, 1, 0] - } + }, + primitiveType: PrimitiveType.TRIANGLES }); mesh = GeometryFilters.computeNormal(mesh); @@ -1060,9 +1059,9 @@ defineSuite([ } }, indexList : { - primitiveType: PrimitiveType.TRIANGLE_STRIP, values: [0, 1, 2] - } + }, + primitiveType: PrimitiveType.TRIANGLE_STRIP }); mesh = GeometryFilters.computeTangentAndBinormal(mesh); @@ -1088,9 +1087,9 @@ defineSuite([ } }, indexList : { - primitiveType: PrimitiveType.TRIANGLES, values: [0, 1, 2] - } + }, + primitiveType: PrimitiveType.TRIANGLES }); mesh = GeometryFilters.computeNormal(mesh); @@ -1119,9 +1118,9 @@ defineSuite([ } }, indexList : { - primitiveType: PrimitiveType.TRIANGLES, values: [0, 1, 2, 1, 3, 2] - } + }, + primitiveType: PrimitiveType.TRIANGLES }); mesh = GeometryFilters.computeNormal(mesh); From da2f6cfc94baaaecb48869060dbc5782acccb7b0 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Wed, 5 Jun 2013 12:11:31 -0400 Subject: [PATCH 142/306] Add use of Geometry and GeometryAttribute to Geometry Filter tets --- Source/Scene/ImageryLayer.js | 12 +- Specs/Core/GeometryFiltersSpec.js | 512 +++++++++++++----------------- 2 files changed, 222 insertions(+), 302 deletions(-) diff --git a/Source/Scene/ImageryLayer.js b/Source/Scene/ImageryLayer.js index 0e7eebabb122..b40da15ef5bb 100644 --- a/Source/Scene/ImageryLayer.js +++ b/Source/Scene/ImageryLayer.js @@ -10,6 +10,8 @@ define([ '../Core/Extent', '../Core/Math', '../Core/PrimitiveType', + '../Core/Geometry', + '../Core/GeometryAttribute', '../Renderer/BufferUsage', '../Renderer/MipmapHint', '../Renderer/TextureMagnificationFilter', @@ -37,6 +39,8 @@ define([ Extent, CesiumMath, PrimitiveType, + Geometry, + GeometryAttribute, BufferUsage, MipmapHint, TextureMagnificationFilter, @@ -795,19 +799,19 @@ define([ } } - var reprojectMesh = { + var reprojectMesh = new Geometry({ attributes : { - position : { + position : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 2, values : positions - } + }) }, indexList : { values : TerrainProvider.getRegularGridIndices(256, 256) }, primitiveType : PrimitiveType.TRIANGLES - }; + }); var reprojectAttribInds = { position : 0 diff --git a/Specs/Core/GeometryFiltersSpec.js b/Specs/Core/GeometryFiltersSpec.js index 6dbe72b32a4d..a70c49d96c23 100644 --- a/Specs/Core/GeometryFiltersSpec.js +++ b/Specs/Core/GeometryFiltersSpec.js @@ -35,12 +35,12 @@ defineSuite([ /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/ it('converts triangles to wireframe in place', function() { - var mesh = GeometryFilters.toWireframe({ + var mesh = GeometryFilters.toWireframe(new Geometry({ indexList : { values : [0, 1, 2, 3, 4, 5] }, primitiveType : PrimitiveType.TRIANGLES - }); + })); expect(mesh.primitiveType).toEqual(PrimitiveType.LINES); @@ -63,12 +63,12 @@ defineSuite([ }); it('converts a triangle fan to wireframe in place', function() { - var mesh = GeometryFilters.toWireframe({ + var mesh = GeometryFilters.toWireframe(new Geometry({ indexList : { values : [0, 1, 2, 3] }, primitiveType : PrimitiveType.TRIANGLE_FAN - }); + })); expect(mesh.primitiveType).toEqual(PrimitiveType.LINES); @@ -91,12 +91,12 @@ defineSuite([ }); it('converts a triangle strip to wireframe in place', function() { - var mesh = GeometryFilters.toWireframe({ + var mesh = GeometryFilters.toWireframe(new Geometry({ indexList : { values : [0, 1, 2, 3] }, primitiveType : PrimitiveType.TRIANGLE_STRIP - }); + })); expect(mesh.primitiveType).toEqual(PrimitiveType.LINES); @@ -119,13 +119,13 @@ defineSuite([ }); it('creates attribute indices', function() { - var mesh = { + var mesh = new Geometry({ attributes : { - position : {}, - normal : {}, - color : {} + position : new GeometryAttribute(), + normal : new GeometryAttribute(), + color : new GeometryAttribute() } - }; + }); var indices = GeometryFilters.createAttributeIndices(mesh); @@ -157,45 +157,45 @@ defineSuite([ it('throws an exception when mesh properties have a different number of attributes', function() { expect(function() { - var mesh = {}; - mesh.attributes = {}; - - mesh.attributes.attribute1 = { - componentDatatype : ComponentDatatype.FLOAT, - componentsPerAttribute : 1, - values : [0, 1, 2] - }; - - mesh.attributes.attribute2 = { - componentDatatype : ComponentDatatype.FLOAT, - componentsPerAttribute : 3, - values : [0, 1, 2, 3, 4, 5] - }; + var mesh = new Geometry({ + attributes : { + attribute1 : new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 1, + values : [0, 1, 2] + }), + attribute2 : new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : [0, 1, 2, 3, 4, 5] + }) + } + }); + mesh = GeometryFilters.reorderForPreVertexCache(mesh); }).toThrow(); }); it('can reorder all indices and attributes for the pre vertex cahce', function() { - var mesh = {}; - mesh.attributes = {}; - - mesh.indexList = { - values : [5, 3, 2, 0, 1, 4, 4, 1, 3, 2, 5, 0] - }; - - mesh.primitiveType = PrimitiveType.TRIANGLES; - - mesh.attributes.vertexNames = { - componentDatatype : ComponentDatatype.FLOAT, - componentsPerAttribute : 1, - values : ['v0', 'v1', 'v2', 'v3', 'v4', 'v5'] - }; + var mesh = new Geometry({ + attributes : { + weight : new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 1, + values : [0.0, 1.0, 2.0, 3.0, 4.0, 5.0] + }), + positions : new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0] + }) + }, + indexList : { + values : [5, 3, 2, 0, 1, 4, 4, 1, 3, 2, 5, 0] + }, + primitiveType : PrimitiveType.TRIANGLES + }); - mesh.attributes.positions = { - componentDatatype : ComponentDatatype.FLOAT, - componentsPerAttribute : 3, - values : [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17] - }; GeometryFilters.reorderForPreVertexCache(mesh); expect(mesh.indexList.values[0]).toEqual(0); @@ -211,12 +211,12 @@ defineSuite([ expect(mesh.indexList.values[10]).toEqual(0); expect(mesh.indexList.values[11]).toEqual(3); - expect(mesh.attributes.vertexNames.values[0]).toEqual('v5'); - expect(mesh.attributes.vertexNames.values[1]).toEqual('v3'); - expect(mesh.attributes.vertexNames.values[2]).toEqual('v2'); - expect(mesh.attributes.vertexNames.values[3]).toEqual('v0'); - expect(mesh.attributes.vertexNames.values[4]).toEqual('v1'); - expect(mesh.attributes.vertexNames.values[5]).toEqual('v4'); + expect(mesh.attributes.weight.values[0]).toEqual(5.0); + expect(mesh.attributes.weight.values[1]).toEqual(3.0); + expect(mesh.attributes.weight.values[2]).toEqual(2.0); + expect(mesh.attributes.weight.values[3]).toEqual(0.0); + expect(mesh.attributes.weight.values[4]).toEqual(1.0); + expect(mesh.attributes.weight.values[5]).toEqual(4.0); expect(mesh.attributes.positions.values[0]).toEqual(15); expect(mesh.attributes.positions.values[1]).toEqual(16); @@ -264,24 +264,24 @@ defineSuite([ }); it('fitToUnsignedShortIndices does not change mesh', function() { - var mesh = { + var mesh = new Geometry({ attributes : { - time : { + time : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 1, values : [10.0] - }, - heat : { + }), + heat : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 1, values : [1.0] - } + }) }, indexList : { values : [0, 0, 0] }, primitiveType : PrimitiveType.TRIANGLES - }; + }); var meshes = GeometryFilters.fitToUnsignedShortIndices(mesh); @@ -296,19 +296,19 @@ defineSuite([ times.push(i); } - var mesh = { + var mesh = new Geometry({ attributes : { - time : { + time : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 1, values : times - } + }) }, indexList : { values : [0, 0, 0, sixtyFourK, sixtyFourK, sixtyFourK, 0, sixtyFourK, 0] }, primitiveType : PrimitiveType.TRIANGLES - }; + }); var meshes = GeometryFilters.fitToUnsignedShortIndices(mesh); @@ -335,19 +335,19 @@ defineSuite([ } indices.push(0, 1, 2); - var mesh = { + var mesh = new Geometry({ attributes : { - position : { + position : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 3, values : positions - } + }) }, indexList : { values : indices }, primitiveType : PrimitiveType.TRIANGLES - }; + }); var meshes = GeometryFilters.fitToUnsignedShortIndices(mesh); @@ -361,19 +361,19 @@ defineSuite([ }); it('fitToUnsignedShortIndices throws without triangles', function() { - var mesh = { + var mesh = new Geometry({ attributes : { - time : { + time : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 1, values : [10.0] - } + }) }, indexList : { values : [0] }, primitiveType : PrimitiveType.POINTS - }; + }); expect(function() { return GeometryFilters.fitToUnsignedShortIndices(mesh); @@ -381,25 +381,24 @@ defineSuite([ }); it('fitToUnsignedShortIndices throws with different numbers of attributes', function() { - var mesh = { + var mesh = new Geometry({ attributes : { - time : { + time : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 1, values : [10.0] - }, - - heat : { + }), + heat : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 1, values : [1.0, 2.0] - } + }) }, indexList : { values : [0, 0, 0] }, primitiveType : PrimitiveType.TRIANGLES - }; + }); expect(function() { return GeometryFilters.fitToUnsignedShortIndices(mesh); @@ -442,15 +441,15 @@ defineSuite([ var c = new Cartesian3(-10000000.0, 0.0, 10000000.0); var encoded = EncodedCartesian3.fromCartesian(c); - var mesh = { + var mesh = new Geometry({ attributes : { - position : { + position : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 3, values : [c.x, c.y, c.z] - } + }) } - }; + }); mesh = GeometryFilters.encodeAttribute(mesh); expect(mesh.attributes.positionHigh).toBeDefined(); @@ -478,23 +477,19 @@ defineSuite([ it('GeometryFilters.encodeAttribute throws without attribute', function() { expect(function() { - var mesh = { - attributes : { - } - }; - GeometryFilters.encodeAttribute(mesh); + GeometryFilters.encodeAttribute(new Geometry()); }).toThrow(); }); it('GeometryFilters.encodeAttribute throws without ComponentDatatype.FLOAT', function() { expect(function() { - var mesh = { - attributes : { + var mesh = new Geometry({ + attributes : new GeometryAttribute({ componentDatatype : ComponentDatatype.UNSIGNED_SHORT, componentsPerAttribute : 1, values : [0.0] - } - }; + }) + }); GeometryFilters.encodeAttribute(mesh); }).toThrow(); }); @@ -606,25 +601,17 @@ defineSuite([ }).toThrow(); }); - it('GeometryFilters.computeNormal throws when mesh.attributes is undefined', function() { - expect(function() { - GeometryFilters.computeNormal(new Geometry()); - }).toThrow(); - }); - it('GeometryFilters.computeNormal throws when mesh.attributes.position is undefined', function() { expect(function() { - GeometryFilters.computeNormal(new Geometry( { - attributes: {} - })); + GeometryFilters.computeNormal(new Geometry()); }).toThrow(); }); it('GeometryFilters.computeNormal throws when mesh.attributes.position.values is undefined', function() { expect(function() { - GeometryFilters.computeNormal(new Geometry( { + GeometryFilters.computeNormal(new Geometry({ attributes: { - position: {} + position: new GeometryAttribute() } })); }).toThrow(); @@ -632,12 +619,12 @@ defineSuite([ it('GeometryFilters.computeNormal throws when mesh.attributes.position.componentsPerAttribute is not 3', function() { expect(function() { - GeometryFilters.computeNormal(new Geometry( { + GeometryFilters.computeNormal(new Geometry({ attributes: { - position: { - values: [3, 2, 1, 1, 2, 4], - componentsPerAttribute: 2 - } + position: new GeometryAttribute({ + values : [3, 2, 1, 1, 2, 4], + componentsPerAttribute : 2 + }) } })); }).toThrow(); @@ -647,10 +634,10 @@ defineSuite([ expect(function() { GeometryFilters.computeNormal(new Geometry( { attributes: { - position: { + position: new GeometryAttribute({ values: [3, 2, 1, 1, 2, 4, 3], componentsPerAttribute: 3 - } + }) } })); }).toThrow(); @@ -659,12 +646,10 @@ defineSuite([ it('GeometryFilters.computeNormal does not compute normals when mesh.indexList is undefined', function() { var mesh = new Geometry({ attributes: { - position: { - values: [0, 0, 0, - 1, 0, 0, - 0, 1, 0], + position: new GeometryAttribute({ + values: [0, 0, 0, 1, 0, 0, 0, 1, 0], componentsPerAttribute: 3 - } + }) } }); @@ -676,13 +661,10 @@ defineSuite([ it('GeometryFilters.computeNormal does not compute normals when primitive type is not triangle', function() { var mesh = new Geometry({ attributes: { - position: { - values: [0, 0, 0, - 1, 0, 0, - 0, 1, 0], - componentsPerAttribute: 3 - - } + position: new GeometryAttribute({ + values: [0, 0, 0, 1, 0, 0, 0, 1, 0], + componentsPerAttribute: 3 + }) }, indexList : { values: [0, 1, 2] @@ -699,12 +681,10 @@ defineSuite([ it('GeometryFilters.computeNormal computes normal for one triangle', function() { var mesh = new Geometry({ attributes: { - position: { - values: [0, 0, 0, - 1, 0, 0, - 0, 1, 0], - componentsPerAttribute: 3 - } + position: new GeometryAttribute({ + values: [0, 0, 0, 1, 0, 0, 0, 1, 0], + componentsPerAttribute: 3 + }) }, indexList : { values: [0, 1, 2] @@ -721,13 +701,10 @@ defineSuite([ it('GeometryFilters.computeNormal computes normal for two triangles', function() { var mesh = new Geometry({ attributes: { - position: { - values: [0, 0, 0, - 1, 0, 1, - 1, 1, 1, - 2, 0, 0], - componentsPerAttribute: 3 - } + position: new GeometryAttribute({ + values: [0, 0, 0, 1, 0, 1, 1, 1, 1, 2, 0, 0], + componentsPerAttribute: 3 + }) }, indexList : { values: [0, 1, 2, 1, 3, 2] @@ -748,16 +725,10 @@ defineSuite([ it('GeometryFilters.computeNormal computes normal for six triangles', function() { var mesh = new Geometry ({ attributes: { - position: { - values: [0, 0, 0, - 1, 0, 0, - 1, 0, 1, - 0, 0, 1, - 0, 1, 1, - 0, 1, 0, - 1, 1, 0], - componentsPerAttribute: 3 - } + position: new GeometryAttribute({ + values: [0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0], + componentsPerAttribute: 3 + }) }, indexList : { values: [0, 1, 2, 3, 0, 2, 4, 0, 3, 4, 5, 0, 5, 6, 0, 6, 1, 0] @@ -787,15 +758,9 @@ defineSuite([ }).toThrow(); }); - it('GeometryFilters.computeTangentAndBinormal throws when mesh.attributes is undefined', function() { - expect(function() { - GeometryFilters.computeTangentAndBinormal(new Geometry()); - }).toThrow(); - }); - it('GeometryFilters.computeTangentAndBinormal throws when mesh.attributes.position is undefined', function() { expect(function() { - GeometryFilters.computeTangentAndBinormal(new Geometry( { + GeometryFilters.computeTangentAndBinormal(new Geometry({ attributes: {} })); }).toThrow(); @@ -803,9 +768,9 @@ defineSuite([ it('GeometryFilters.computeTangentAndBinormal throws when mesh.attributes.position.values is undefined', function() { expect(function() { - GeometryFilters.computeTangentAndBinormal(new Geometry( { + GeometryFilters.computeTangentAndBinormal(new Geometry({ attributes: { - position: {} + position: new GeometryAttribute() } })); }).toThrow(); @@ -813,12 +778,12 @@ defineSuite([ it('GeometryFilters.computeTangentAndBinormal throws when mesh.attributes.position.componentsPerAttribute is not 3', function() { expect(function() { - GeometryFilters.computeTangentAndBinormal(new Geometry( { + GeometryFilters.computeTangentAndBinormal(new Geometry({ attributes: { - position: { + position: new GeometryAttribute({ values: [3, 2, 1, 1, 2, 4], componentsPerAttribute: 2 - } + }) } })); }).toThrow(); @@ -826,12 +791,12 @@ defineSuite([ it('GeometryFilters.computeTangentAndBinormal throws when mesh.attributes.position.values is not a multiple of 3', function() { expect(function() { - GeometryFilters.computeTangentAndBinormal(new Geometry( { + GeometryFilters.computeTangentAndBinormal(new Geometry({ attributes: { - position: { + position: new GeometryAttribute({ values: [3, 2, 1, 1, 2, 4, 3], componentsPerAttribute: 3 - } + }) } })); }).toThrow(); @@ -839,15 +804,12 @@ defineSuite([ it('GeometryFilters.computeTangentAndBinormal throws when mesh.attributes.normal is undefined', function() { expect(function() { - GeometryFilters.computeTangentAndBinormal(new Geometry( { + GeometryFilters.computeTangentAndBinormal(new Geometry({ attributes: { - position: { - values: [0, 0, 0, - 1, 0, 0, - 0, 1, 0], - componentsPerAttribute: 3 - - } + position: new GeometryAttribute({ + values: [0, 0, 0, 1, 0, 0, 0, 1, 0], + componentsPerAttribute: 3 + }) } })); }).toThrow(); @@ -855,15 +817,12 @@ defineSuite([ it('GeometryFilters.computeTangentAndBinormal throws when mesh.attributes.normal.values is undefined', function() { expect(function() { - GeometryFilters.computeTangentAndBinormal(new Geometry( { + GeometryFilters.computeTangentAndBinormal(new Geometry({ attributes: { - position: { - values: [0, 0, 0, - 1, 0, 0, - 0, 1, 0], - componentsPerAttribute: 3 - - }, + position: new GeometryAttribute({ + values: [0, 0, 0, 1, 0, 0, 0, 1, 0], + componentsPerAttribute: 3 + }), normal: {} } })); @@ -872,16 +831,16 @@ defineSuite([ it('GeometryFilters.computeTangentAndBinormal throws when mesh.attributes.normal.componentsPerAttribute is not 3', function() { expect(function() { - GeometryFilters.computeTangentAndBinormal(new Geometry( { + GeometryFilters.computeTangentAndBinormal(new Geometry({ attributes: { - position: { + position: new GeometryAttribute({ values: [3, 2, 1, 1, 2, 4], componentsPerAttribute: 3 - }, - normal: { + }), + normal: new GeometryAttribute({ values: [3, 2, 1, 1, 2, 4], componentsPerAttribute: 2 - } + }) } })); }).toThrow(); @@ -889,16 +848,16 @@ defineSuite([ it('GeometryFilters.computeTangentAndBinormal throws when mesh.attributes.normal.values is not a multiple of 3', function() { expect(function() { - GeometryFilters.computeTangentAndBinormal(new Geometry( { + GeometryFilters.computeTangentAndBinormal(new Geometry({ attributes: { - position: { + position: new GeometryAttribute({ values: [3, 2, 1, 1, 2, 3], componentsPerAttribute: 3 - }, - normal: { + }), + normal: new GeometryAttribute({ values: [3, 2, 1, 1, 2, 3, 4], componentsPerAttribute: 3 - } + }) } })); }).toThrow(); @@ -908,20 +867,15 @@ defineSuite([ expect(function() { GeometryFilters.computeTangentAndBinormal(new Geometry( { attributes: { - position: { - values: [0, 0, 0, - 1, 0, 0, - 0, 1, 0], - componentsPerAttribute: 3 - - }, - normal: { - values: [0, 0, 0, - 1, 0, 0, - 0, 1, 0], - componentsPerAttribute: 3 + position: new GeometryAttribute({ + values: [0, 0, 0, 1, 0, 0, 0, 1, 0], + componentsPerAttribute: 3 - } + }), + normal: new GeometryAttribute({ + values: [0, 0, 0, 1, 0, 0, 0, 1, 0], + componentsPerAttribute: 3 + }) } })); }).toThrow(); @@ -931,21 +885,15 @@ defineSuite([ expect(function() { GeometryFilters.computeTangentAndBinormal(new Geometry( { attributes: { - position: { - values: [0, 0, 0, - 1, 0, 0, - 0, 1, 0], - componentsPerAttribute: 3 - - }, - normal: { - values: [0, 0, 0, - 1, 0, 0, - 0, 1, 0], - componentsPerAttribute: 3 - - }, - st: {} + position: new GeometryAttribute({ + values: [0, 0, 0, 1, 0, 0, 0, 1, 0], + componentsPerAttribute: 3 + }), + normal: new GeometryAttribute({ + values: [0, 0, 0, 1, 0, 0, 0, 1, 0], + componentsPerAttribute: 3 + }), + st: new GeometryAttribute() } })); }).toThrow(); @@ -955,24 +903,18 @@ defineSuite([ expect(function() { GeometryFilters.computeTangentAndBinormal(new Geometry( { attributes: { - position: { - values: [0, 0, 0, - 1, 0, 0, - 0, 1, 0], - componentsPerAttribute: 3 - - }, - normal: { - values: [0, 0, 0, - 1, 0, 0, - 0, 1, 0], - componentsPerAttribute: 3 - - }, - st: { + position: new GeometryAttribute({ + values: [0, 0, 0, 1, 0, 0, 0, 1, 0], + componentsPerAttribute: 3 + }), + normal: new GeometryAttribute({ + values: [0, 0, 0, 1, 0, 0, 0, 1, 0], + componentsPerAttribute: 3 + }), + st: new GeometryAttribute({ values: [0, 1], componentsPerAttribute: 3 - } + }) } })); }).toThrow(); @@ -982,51 +924,39 @@ defineSuite([ expect(function() { GeometryFilters.computeTangentAndBinormal(new Geometry( { attributes: { - position: { - values: [0, 0, 0, - 1, 0, 0, - 0, 1, 0], - componentsPerAttribute: 3 - - }, - normal: { - values: [0, 0, 0, - 1, 0, 0, - 0, 1, 0], - componentsPerAttribute: 3 - - }, - st: { + position: new GeometryAttribute({ + values: [0, 0, 0, 1, 0, 0, 0, 1, 0], + componentsPerAttribute: 3 + }), + normal: new GeometryAttribute({ + values: [0, 0, 0, 1, 0, 0, 0, 1, 0], + componentsPerAttribute: 3 + }), + st: new GeometryAttribute({ values: [0, 1, 3], componentsPerAttribute: 2 - } + }) } })); }).toThrow(); }); - it('GeometryFilters.computeTangentAndBinormal does not compute tangent and binormals when mesh.indexList is undefined', function() { var mesh = new Geometry({ attributes: { - position: { - values: [0, 0, 0, - 1, 0, 0, - 0, 1, 0], - componentsPerAttribute: 3 - - }, - normal: { - values: [0, 0, 0, - 1, 0, 0, - 0, 1, 0], - componentsPerAttribute: 3 + position: new GeometryAttribute({ + values: [0, 0, 0, 1, 0, 0, 0, 1, 0], + componentsPerAttribute: 3 + }), + normal: new GeometryAttribute({ + values: [0, 0, 0, 1, 0, 0, 0, 1, 0], + componentsPerAttribute: 3 - }, - st: { + }), + st: new GeometryAttribute({ values: [0, 1], componentsPerAttribute: 2 - } + }) } }); @@ -1039,24 +969,20 @@ defineSuite([ it('GeometryFilters.computeTangentAndBinormal does not compute tangent and binormals when primitive type is not triangle', function() { var mesh = new Geometry({ attributes: { - position: { - values: [0, 0, 0, - 1, 0, 0, - 0, 1, 0], - componentsPerAttribute: 3 + position: new GeometryAttribute({ + values: [0, 0, 0, 1, 0, 0, 0, 1, 0], + componentsPerAttribute: 3 - }, - normal: { - values: [0, 0, 0, - 1, 0, 0, - 0, 1, 0], - componentsPerAttribute: 3 + }), + normal: new GeometryAttribute({ + values: [0, 0, 0, 1, 0, 0, 0, 1, 0], + componentsPerAttribute: 3 - }, - st: { + }), + st: new GeometryAttribute({ values: [0, 1], componentsPerAttribute: 2 - } + }) }, indexList : { values: [0, 1, 2] @@ -1073,18 +999,14 @@ defineSuite([ it('GeometryFilters.computeTangentAndBinormal computes tangent and binormal for one triangle', function() { var mesh = new Geometry({ attributes: { - position: { - values: [0, 0, 0, - 1, 0, 0, - 0, 1, 0], - componentsPerAttribute: 3 - }, - st: { - values: [0, 0, - 1, 0, - 0, 1], - componentsPerAttribute: 2 - } + position: new GeometryAttribute({ + values: [0, 0, 0, 1, 0, 0, 0, 1, 0], + componentsPerAttribute: 3 + }), + st: new GeometryAttribute({ + values: [0, 0, 1, 0, 0, 1], + componentsPerAttribute: 2 + }) }, indexList : { values: [0, 1, 2] @@ -1102,20 +1024,14 @@ defineSuite([ it('GeometryFilters.computeTangentAndBinormal computes tangent and binormal for two triangles', function() { var mesh = new Geometry({ attributes: { - position: { - values: [0, 0, 0, - 1, 0, 1, - 1, 1, 1, - 2, 0, 0], - componentsPerAttribute: 3 - }, - st: { - values: [0, 0, - 1, 0, - 1, 1, - 0, 1], - componentsPerAttribute: 2 - } + position: new GeometryAttribute({ + values: [0, 0, 0, 1, 0, 1, 1, 1, 1, 2, 0, 0], + componentsPerAttribute: 3 + }), + st: new GeometryAttribute({ + values: [0, 0, 1, 0, 1, 1, 0, 1], + componentsPerAttribute: 2 + }) }, indexList : { values: [0, 1, 2, 1, 3, 2] From b1405b55c5fe40a808b350dcdda6e5af5f59fffb Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Wed, 5 Jun 2013 15:10:05 -0400 Subject: [PATCH 143/306] Removed GeometryIndices.js --- Source/Core/BoxGeometry.js | 80 ++++++------ Source/Core/CircleGeometry.js | 2 +- Source/Core/EllipseGeometry.js | 8 +- Source/Core/EllipsoidGeometry.js | 8 +- Source/Core/ExtentGeometry.js | 8 +- Source/Core/Geometry.js | 12 +- Source/Core/GeometryFilters.js | 47 +++---- Source/Core/GeometryIndices.js | 44 ------- Source/Core/PolygonGeometry.js | 2 +- Source/Core/PolygonPipeline.js | 8 +- Source/Core/PolylinePipeline.js | 2 + Source/Core/WallGeometry.js | 8 +- Source/Renderer/Context.js | 4 +- Source/Scene/CentralBody.js | 4 +- Source/Scene/ImageryLayer.js | 4 +- Specs/Core/BoxGeometrySpec.js | 4 +- Specs/Core/CircleGeometrySpec.js | 4 +- Specs/Core/EllipseGeometrySpec.js | 4 +- Specs/Core/EllipsoidGeometrySpec.js | 4 +- Specs/Core/ExtentGeometrySpec.js | 8 +- Specs/Core/GeometryFiltersSpec.js | 118 ++++++----------- Specs/Core/PolygonGeometrySpec.js | 8 +- Specs/Core/PolygonPipelineSpec.js | 6 +- Specs/Core/WallGeometrySpec.js | 6 +- Specs/Renderer/VertexArrayFactorySpec.js | 160 ++++++++++++----------- 25 files changed, 225 insertions(+), 338 deletions(-) delete mode 100644 Source/Core/GeometryIndices.js diff --git a/Source/Core/BoxGeometry.js b/Source/Core/BoxGeometry.js index 368a0216f698..0cfae61808eb 100644 --- a/Source/Core/BoxGeometry.js +++ b/Source/Core/BoxGeometry.js @@ -8,7 +8,6 @@ define([ './BoundingSphere', './Geometry', './GeometryAttribute', - './GeometryIndices', './VertexFormat' ], function( DeveloperError, @@ -19,7 +18,6 @@ define([ BoundingSphere, Geometry, GeometryAttribute, - GeometryIndices, VertexFormat) { "use strict"; @@ -292,34 +290,32 @@ define([ }); } - indexList = new GeometryIndices({ - // 12 triangles: 6 faces, 2 triangles each. - values : [ - // +z face - 0, 1, 2, - 0, 2, 3, + // 12 triangles: 6 faces, 2 triangles each. + indexList = [ + // +z face + 0, 1, 2, + 0, 2, 3, - // -z face - 4 + 2, 4 + 1, 4 + 0, - 4 + 3, 4 + 2, 4 + 0, + // -z face + 4 + 2, 4 + 1, 4 + 0, + 4 + 3, 4 + 2, 4 + 0, - // +x face - 8 + 0, 8 + 1, 8 + 2, - 8 + 0, 8 + 2, 8 + 3, + // +x face + 8 + 0, 8 + 1, 8 + 2, + 8 + 0, 8 + 2, 8 + 3, - // -x face - 12 + 2, 12 + 1, 12 + 0, - 12 + 3, 12 + 2, 12 + 0, + // -x face + 12 + 2, 12 + 1, 12 + 0, + 12 + 3, 12 + 2, 12 + 0, - // +y face - 16 + 2, 16 + 1, 16 + 0, - 16 + 3, 16 + 2, 16 + 0, + // +y face + 16 + 2, 16 + 1, 16 + 0, + 16 + 3, 16 + 2, 16 + 0, - // -y face - 20 + 0, 20 + 1, 20 + 2, - 20 + 0, 20 + 2, 20 + 3 - ] - }); + // -y face + 20 + 0, 20 + 1, 20 + 2, + 20 + 0, 20 + 2, 20 + 3 + ]; } else { // Positions only - no need to duplicate corner points attributes.position = new GeometryAttribute({ @@ -338,23 +334,21 @@ define([ ] }); - indexList = new GeometryIndices({ - // 12 triangles: 6 faces, 2 triangles each. - values : [ - 4, 5, 6, // plane z = corner.Z - 4, 6, 7, - 1, 0, 3, // plane z = -corner.Z - 1, 3, 2, - 1, 6, 5, // plane x = corner.X - 1, 2, 6, - 2, 3, 7, // plane y = corner.Y - 2, 7, 6, - 3, 0, 4, // plane x = -corner.X - 3, 4, 7, - 0, 1, 5, // plane y = -corner.Y - 0, 5, 4 - ] - }); + // 12 triangles: 6 faces, 2 triangles each. + indexList = [ + 4, 5, 6, // plane z = corner.Z + 4, 6, 7, + 1, 0, 3, // plane z = -corner.Z + 1, 3, 2, + 1, 6, 5, // plane x = corner.X + 1, 2, 6, + 2, 3, 7, // plane y = corner.Y + 2, 7, 6, + 3, 0, 4, // plane x = -corner.X + 3, 4, 7, + 0, 1, 5, // plane y = -corner.Y + 0, 5, 4 + ]; } /** @@ -368,7 +362,7 @@ define([ /** * The geometry indices. * - * @type GeometryIndices + * @type Array */ this.indexList = indexList; diff --git a/Source/Core/CircleGeometry.js b/Source/Core/CircleGeometry.js index aa9f8e6f5b42..708e9f214439 100644 --- a/Source/Core/CircleGeometry.js +++ b/Source/Core/CircleGeometry.js @@ -68,7 +68,7 @@ define([ /** * The geometry indices. * - * @type GeometryIndices + * @type Array */ this.indexList = ellipseGeometry.indexList; diff --git a/Source/Core/EllipseGeometry.js b/Source/Core/EllipseGeometry.js index 523cf2913bac..f51486f920fb 100644 --- a/Source/Core/EllipseGeometry.js +++ b/Source/Core/EllipseGeometry.js @@ -8,7 +8,6 @@ define([ './Ellipsoid', './Geometry', './GeometryAttribute', - './GeometryIndices', './Math', './Matrix3', './PrimitiveType', @@ -23,7 +22,6 @@ define([ Ellipsoid, Geometry, GeometryAttribute, - GeometryIndices, CesiumMath, Matrix3, PrimitiveType, @@ -434,11 +432,9 @@ define([ /** * The geometry indices. * - * @type GeometryIndices + * @type Array */ - this.indexList = new GeometryIndices({ - values : indices - }); + this.indexList = indices; /** * DOC_TBA diff --git a/Source/Core/EllipsoidGeometry.js b/Source/Core/EllipsoidGeometry.js index efec94de3e6b..ec7e6812d84c 100644 --- a/Source/Core/EllipsoidGeometry.js +++ b/Source/Core/EllipsoidGeometry.js @@ -10,7 +10,6 @@ define([ './BoundingSphere', './Geometry', './GeometryAttribute', - './GeometryIndices', './VertexFormat' ], function( defaultValue, @@ -23,7 +22,6 @@ define([ BoundingSphere, Geometry, GeometryAttribute, - GeometryIndices, VertexFormat) { "use strict"; @@ -318,11 +316,9 @@ define([ /** * The geometry indices. * - * @type GeometryIndices + * @type Array */ - this.indexList = new GeometryIndices({ - values : indices - }); + this.indexList = indices; /** * DOC_TBA diff --git a/Source/Core/ExtentGeometry.js b/Source/Core/ExtentGeometry.js index aff632557085..191493d61526 100644 --- a/Source/Core/ExtentGeometry.js +++ b/Source/Core/ExtentGeometry.js @@ -12,7 +12,6 @@ define([ './GeographicProjection', './Geometry', './GeometryAttribute', - './GeometryIndices', './Math', './Matrix2', './PrimitiveType', @@ -30,7 +29,6 @@ define([ GeographicProjection, Geometry, GeometryAttribute, - GeometryIndices, CesiumMath, Matrix2, PrimitiveType, @@ -306,11 +304,9 @@ define([ /** * The geometry indices. * - * @type GeometryIndices + * @type Array */ - this.indexList = new GeometryIndices({ - values : indices - }); + this.indexList = indices; /** * DOC_TBA diff --git a/Source/Core/Geometry.js b/Source/Core/Geometry.js index d5e86d60797e..57c718423bab 100644 --- a/Source/Core/Geometry.js +++ b/Source/Core/Geometry.js @@ -53,9 +53,17 @@ define([ newAttributes[property] = attributes[property].clone(); } } - result.attributes = newAttributes; - result.indexList = (typeof this.indexList !== 'undefined') ? this.indexList.clone() : undefined; + +// TODO: typed array or not. fastest way to copy? + var sourceValues = this.indexList; + var length = sourceValues.length; + var values = new Array(length); + for (var i = 0; i < length; ++i) { + values[i] = sourceValues[i]; + } + result.indexList = values; + result.primitiveType = this.primitiveType; this.boundingSphere.clone(result.boundingSphere); diff --git a/Source/Core/GeometryFilters.js b/Source/Core/GeometryFilters.js index ee3843bbd2ad..391e70add8ea 100644 --- a/Source/Core/GeometryFilters.js +++ b/Source/Core/GeometryFilters.js @@ -14,7 +14,6 @@ define([ './BoundingSphere', './Geometry', './GeometryAttribute', - './GeometryIndices' ], function( defaultValue, DeveloperError, @@ -29,8 +28,7 @@ define([ Tipsify, BoundingSphere, Geometry, - GeometryAttribute, - GeometryIndices) { + GeometryAttribute) { "use strict"; /** @@ -43,9 +41,9 @@ define([ var GeometryFilters = {}; /** - * Converts a mesh's triangle indices to line indices. Each list of indices in the mesh's indexList with + * Converts a mesh's triangle indices to line indices. The mesh's indexList with * a primitive type of triangles, triangleStrip, or trangleFan is converted to a - * list of indices with a primitive type of lines. Lists of indices with other primitive types remain unchanged. + * list of indices with a primitive type of lines. *

    * The mesh argument should use the standard layout like the mesh returned by {@link BoxGeometry}. *

    @@ -115,13 +113,13 @@ define([ if (typeof indices !== 'undefined') { switch (mesh.primitiveType) { case PrimitiveType.TRIANGLES: - indices.values = trianglesToLines(indices.values); + mesh.indexList = trianglesToLines(indices); break; case PrimitiveType.TRIANGLE_STRIP: - indices.values = triangleStripToLines(indices.values); + mesh.indexList = triangleStripToLines(indices); break; case PrimitiveType.TRIANGLE_FAN: - indices.values = triangleFanToLines(indices.values); + mesh.indexList = triangleFanToLines(indices); break; } @@ -200,7 +198,7 @@ define([ //Construct cross reference and reorder indices var indexList = mesh.indexList; if (typeof indexList !== 'undefined') { - var indicesIn = indexList.values; + var indicesIn = indexList; var numIndices = indicesIn.length; var indicesOut = []; var intoIndicesIn = 0; @@ -224,7 +222,7 @@ define([ ++intoIndicesIn; ++intoIndicesOut; } - mesh.indexList.values = indicesOut; + mesh.indexList = indicesOut; } //Reorder Vertices @@ -278,7 +276,7 @@ define([ */ GeometryFilters.reorderForPostVertexCache = function(mesh, cacheCapacity) { if (typeof mesh !== 'undefined') { - var indices = mesh.indexList.values; + var indices = mesh.indexList; if (typeof indices !== 'undefined') { var numIndices = indices.length; var maximumIndex = 0; @@ -287,7 +285,7 @@ define([ maximumIndex = indices[j]; } } - mesh.indexList.values = Tipsify.tipsify({ + mesh.indexList = Tipsify.tipsify({ indices : indices, maximumIndex : maximumIndex, cacheSize : cacheCapacity @@ -338,9 +336,7 @@ define([ // TODO: is this always what we want, for say BoxGeometry? return new Geometry({ attributes : attributes, - indexList : new GeometryIndices({ - values : indices - }), + indexList : indices, primitiveType : primitiveType }); } @@ -363,7 +359,7 @@ define([ var currentIndex = 0; var newAttributes = GeometryFilters._copyAttributesDescriptions(mesh.attributes); - var originalIndices = mesh.indexList.values; + var originalIndices = mesh.indexList; var numberOfIndices = originalIndices.length; for ( var j = 0; j < numberOfIndices; j += 3) { @@ -722,7 +718,7 @@ define([ for (i = 0; i < length; ++i) { indices = instances[i].geometry.indexList; numberOfIndices[primitiveType] = (typeof numberOfIndices[primitiveType] !== 'undefined') ? - (numberOfIndices[primitiveType] += indices.values.length) : indices.values.length; + (numberOfIndices[primitiveType] += indices.length) : indices.length; } // Next, allocate a typed array for indices per primitive type @@ -740,9 +736,7 @@ define([ values = new Uint32Array(num); } - combinedIndexLists.push(new GeometryIndices({ - values : values - })); + combinedIndexLists.push(values); indexListsByPrimitiveType[name] = { values : values, @@ -755,8 +749,7 @@ define([ var offset = 0; for (i = 0; i < length; ++i) { - indices = instances[i].geometry.indexList; - sourceValues = indices.values; + sourceValues = instances[i].geometry.indexList; sourceValuesLength = sourceValues.length; var destValues = indexListsByPrimitiveType[primitiveType].values; var n = indexListsByPrimitiveType[primitiveType].currentOffset; @@ -836,12 +829,11 @@ define([ if (mesh.attributes.position.componentsPerAttribute !== 3 || vertices.length % 3 !== 0) { throw new DeveloperError('mesh.attributes.position.values.length must be a multiple of 3'); } - var indexList = mesh.indexList; - if (typeof indexList === 'undefined') { + var indices = mesh.indexList; + if (typeof indices === 'undefined') { return mesh; } - var indices = indexList.values; if (mesh.primitiveType !== PrimitiveType.TRIANGLES || typeof indices === 'undefined' || indices.length < 2 || indices.length % 3 !== 0) { return mesh; @@ -1001,12 +993,11 @@ define([ throw new DeveloperError('geometry.attributes.st.values.length must be a multiple of 2'); } - var indexList = geometry.indexList; - if (typeof indexList === 'undefined') { + var indices = geometry.indexList; + if (typeof indices === 'undefined') { return geometry; } - var indices = indexList.values; if (geometry.primitiveType !== PrimitiveType.TRIANGLES || typeof indices === 'undefined' || indices.length < 2 || indices.length % 3 !== 0) { return geometry; diff --git a/Source/Core/GeometryIndices.js b/Source/Core/GeometryIndices.js deleted file mode 100644 index cd61b57c290d..000000000000 --- a/Source/Core/GeometryIndices.js +++ /dev/null @@ -1,44 +0,0 @@ -/*global define*/ -define([ - './defaultValue' - ], function( - defaultValue) { - "use strict"; - - /** - * DOC_TBA - * - * @alias GeometryIndices - * @constructor - */ - var GeometryIndices = function(options) { - options = defaultValue(options, defaultValue.EMPTY_OBJECT); - - /** - * DOC_TBA - */ - this.values = options.values; - }; - - /** - * DOC_TBA - */ - GeometryIndices.prototype.clone = function(result) { - if (typeof result === 'undefined') { - result = new GeometryIndices(); - } - -// TODO: typed array or not. fastest way to copy? - var sourceValues = this.values; - var length = sourceValues.length; - var values = new Array(length); - for (var i = 0; i < length; ++i) { - values[i] = sourceValues[i]; - } - result.values = values; - - return result; - }; - - return GeometryIndices; -}); diff --git a/Source/Core/PolygonGeometry.js b/Source/Core/PolygonGeometry.js index 255293845bb6..a623121b55ec 100644 --- a/Source/Core/PolygonGeometry.js +++ b/Source/Core/PolygonGeometry.js @@ -417,7 +417,7 @@ define([ /** * The geometry indices. * - * @type GeometryIndices + * @type Array */ this.indexList = mesh.indexList; diff --git a/Source/Core/PolygonPipeline.js b/Source/Core/PolygonPipeline.js index e90964a5d237..b8f17aaaf8c4 100644 --- a/Source/Core/PolygonPipeline.js +++ b/Source/Core/PolygonPipeline.js @@ -6,7 +6,6 @@ define([ './Cartesian3', './Geometry', './GeometryAttribute', - './GeometryIndices', './Ellipsoid', './EllipsoidTangentPlane', './defaultValue', @@ -22,7 +21,6 @@ define([ Cartesian3, Geometry, GeometryAttribute, - GeometryIndices, Ellipsoid, EllipsoidTangentPlane, defaultValue, @@ -837,11 +835,7 @@ define([ values : flattenedPositions }) }, - - indexList : new GeometryIndices({ - values : subdividedIndices - }), - + indexList : subdividedIndices, primitiveType : PrimitiveType.TRIANGLES }); }, diff --git a/Source/Core/PolylinePipeline.js b/Source/Core/PolylinePipeline.js index a8e5549cab48..20c8862ada4c 100644 --- a/Source/Core/PolylinePipeline.js +++ b/Source/Core/PolylinePipeline.js @@ -1,6 +1,7 @@ /*global define*/ define([ './defaultValue', + './DeveloperError', './Cartesian3', './Cartesian4', './IntersectionTests', @@ -8,6 +9,7 @@ define([ './Plane' ], function( defaultValue, + DeveloperError, Cartesian3, Cartesian4, IntersectionTests, diff --git a/Source/Core/WallGeometry.js b/Source/Core/WallGeometry.js index 087f8eb6932f..92874962b2b1 100644 --- a/Source/Core/WallGeometry.js +++ b/Source/Core/WallGeometry.js @@ -10,7 +10,6 @@ define([ './EllipsoidTangentPlane', './Geometry', './GeometryAttribute', - './GeometryIndices', './PolylinePipeline', './PolygonPipeline', './PrimitiveType', @@ -27,7 +26,6 @@ define([ EllipsoidTangentPlane, Geometry, GeometryAttribute, - GeometryIndices, PolylinePipeline, PolygonPipeline, PrimitiveType, @@ -286,11 +284,9 @@ define([ /** * The geometry indices. * - * @type GeometryIndices + * @type Array */ - this.indexList = new GeometryIndices({ - values : indices - }); + this.indexList = indices; /** * DOC_TBA diff --git a/Source/Renderer/Context.js b/Source/Renderer/Context.js index 65faa9cacbe0..8b18f1f805ed 100644 --- a/Source/Renderer/Context.js +++ b/Source/Renderer/Context.js @@ -2416,9 +2416,9 @@ define([ var indexList = mesh.indexList; if (typeof indexList !== 'undefined') { if ((Geometry.computeNumberOfVertices(mesh) > 64 * 1024) && this.getElementIndexUint()) { - indexBuffer = this.createIndexBuffer(new Uint32Array(indexList.values), bufferUsage, IndexDatatype.UNSIGNED_INT); + indexBuffer = this.createIndexBuffer(new Uint32Array(indexList), bufferUsage, IndexDatatype.UNSIGNED_INT); } else{ - indexBuffer = this.createIndexBuffer(new Uint16Array(indexList.values), bufferUsage, IndexDatatype.UNSIGNED_SHORT); + indexBuffer = this.createIndexBuffer(new Uint16Array(indexList), bufferUsage, IndexDatatype.UNSIGNED_SHORT); } } diff --git a/Source/Scene/CentralBody.js b/Source/Scene/CentralBody.js index 18cf4f93920b..ee17ff90272e 100644 --- a/Source/Scene/CentralBody.js +++ b/Source/Scene/CentralBody.js @@ -549,9 +549,7 @@ define([ values : depthQuad } }, - indexList : { - values : [0, 1, 2, 2, 1, 3] - }, + indexList : [0, 1, 2, 2, 1, 3], primitiveType : PrimitiveType.TRIANGLES }; this._depthCommand.vertexArray = context.createVertexArrayFromMesh({ diff --git a/Source/Scene/ImageryLayer.js b/Source/Scene/ImageryLayer.js index b40da15ef5bb..cc46d5200ff5 100644 --- a/Source/Scene/ImageryLayer.js +++ b/Source/Scene/ImageryLayer.js @@ -807,9 +807,7 @@ define([ values : positions }) }, - indexList : { - values : TerrainProvider.getRegularGridIndices(256, 256) - }, + indexList : TerrainProvider.getRegularGridIndices(256, 256), primitiveType : PrimitiveType.TRIANGLES }); diff --git a/Specs/Core/BoxGeometrySpec.js b/Specs/Core/BoxGeometrySpec.js index 30d49d0f08e0..b4fbe13263d5 100644 --- a/Specs/Core/BoxGeometrySpec.js +++ b/Specs/Core/BoxGeometrySpec.js @@ -27,7 +27,7 @@ defineSuite([ }); expect(m.attributes.position.values.length).toEqual(8 * 3); - expect(m.indexList.values.length).toEqual(12 * 3); + expect(m.indexList.length).toEqual(12 * 3); }); it('constructor computes all vertex attributes', function() { @@ -45,7 +45,7 @@ defineSuite([ expect(m.attributes.binormal.values.length).toEqual(6 * 4 * 3); expect(m.attributes.st.values.length).toEqual(6 * 4 * 2); - expect(m.indexList.values.length).toEqual(12 * 3); + expect(m.indexList.length).toEqual(12 * 3); expect(m.boundingSphere.center).toEqual(Cartesian3.ZERO); expect(m.boundingSphere.radius).toEqual(maximumCorner.magnitude() * 0.5); diff --git a/Specs/Core/CircleGeometrySpec.js b/Specs/Core/CircleGeometrySpec.js index 81af07b3f8b4..fccea149d7d2 100644 --- a/Specs/Core/CircleGeometrySpec.js +++ b/Specs/Core/CircleGeometrySpec.js @@ -60,7 +60,7 @@ defineSuite([ }); expect(m.attributes.position.values.length).toEqual(3 * 24); - expect(m.indexList.values.length).toEqual(3 * 34); + expect(m.indexList.length).toEqual(3 * 34); expect(m.boundingSphere.radius).toEqual(1); }); @@ -79,6 +79,6 @@ defineSuite([ expect(m.attributes.normal.values.length).toEqual(3 * 24); expect(m.attributes.tangent.values.length).toEqual(3 * 24); expect(m.attributes.binormal.values.length).toEqual(3 * 24); - expect(m.indexList.values.length).toEqual(3 * 34); + expect(m.indexList.length).toEqual(3 * 34); }); }); diff --git a/Specs/Core/EllipseGeometrySpec.js b/Specs/Core/EllipseGeometrySpec.js index 8436bf7dff21..4f6876b8418e 100644 --- a/Specs/Core/EllipseGeometrySpec.js +++ b/Specs/Core/EllipseGeometrySpec.js @@ -74,7 +74,7 @@ defineSuite([ }); expect(m.attributes.position.values.length).toEqual(3 * 24); - expect(m.indexList.values.length).toEqual(3 * 34); + expect(m.indexList.length).toEqual(3 * 34); expect(m.boundingSphere.radius).toEqual(1); }); @@ -94,6 +94,6 @@ defineSuite([ expect(m.attributes.normal.values.length).toEqual(3 * 24); expect(m.attributes.tangent.values.length).toEqual(3 * 24); expect(m.attributes.binormal.values.length).toEqual(3 * 24); - expect(m.indexList.values.length).toEqual(3 * 34); + expect(m.indexList.length).toEqual(3 * 34); }); }); diff --git a/Specs/Core/EllipsoidGeometrySpec.js b/Specs/Core/EllipsoidGeometrySpec.js index 1f563bc6bd59..3686782d649c 100644 --- a/Specs/Core/EllipsoidGeometrySpec.js +++ b/Specs/Core/EllipsoidGeometrySpec.js @@ -30,7 +30,7 @@ defineSuite([ }); expect(m.attributes.position.values.length).toEqual(3 * 8); - expect(m.indexList.values.length).toEqual(12 * 3); + expect(m.indexList.length).toEqual(12 * 3); expect(m.boundingSphere.radius).toEqual(1); }); @@ -46,7 +46,7 @@ defineSuite([ expect(m.attributes.normal.values.length).toEqual(3 * (8 + 6 + 12)); expect(m.attributes.tangent.values.length).toEqual(3 * (8 + 6 + 12)); expect(m.attributes.binormal.values.length).toEqual(3 * (8 + 6 + 12)); - expect(m.indexList.values.length).toEqual(2 * 3 * 4 * 6); + expect(m.indexList.length).toEqual(2 * 3 * 4 * 6); }); it('computes attributes for a unit sphere', function() { diff --git a/Specs/Core/ExtentGeometrySpec.js b/Specs/Core/ExtentGeometrySpec.js index 0e039d3b60c7..661b9f85de66 100644 --- a/Specs/Core/ExtentGeometrySpec.js +++ b/Specs/Core/ExtentGeometrySpec.js @@ -31,7 +31,7 @@ defineSuite([ var length = positions.length; expect(positions.length).toEqual(9 * 3); - expect(m.indexList.values.length).toEqual(8 * 3); + expect(m.indexList.length).toEqual(8 * 3); var expectedNWCorner = Ellipsoid.WGS84.cartographicToCartesian(extent.getNorthwest()); var expectedSECorner = Ellipsoid.WGS84.cartographicToCartesian(extent.getSoutheast()); @@ -50,7 +50,7 @@ defineSuite([ expect(m.attributes.normal.values.length).toEqual(9 * 3); expect(m.attributes.tangent.values.length).toEqual(9 * 3); expect(m.attributes.binormal.values.length).toEqual(9 * 3); - expect(m.indexList.values.length).toEqual(8 * 3); + expect(m.indexList.length).toEqual(8 * 3); }); it('compute positions with rotation', function() { @@ -66,7 +66,7 @@ defineSuite([ var length = positions.length; expect(length).toEqual(9 * 3); - expect(m.indexList.values.length).toEqual(8 * 3); + expect(m.indexList.length).toEqual(8 * 3); var unrotatedSECorner = extent.getSoutheast(); var projection = new GeographicProjection(); @@ -89,7 +89,7 @@ defineSuite([ var length = positions.length; expect(length).toEqual(9 * 3); - expect(m.indexList.values.length).toEqual(8 * 3); + expect(m.indexList.length).toEqual(8 * 3); var unrotatedNWCorner = Ellipsoid.WGS84.cartographicToCartesian(extent.getNorthwest()); var unrotatedSECorner = Ellipsoid.WGS84.cartographicToCartesian(extent.getSoutheast()); diff --git a/Specs/Core/GeometryFiltersSpec.js b/Specs/Core/GeometryFiltersSpec.js index a70c49d96c23..cc7e9967cd35 100644 --- a/Specs/Core/GeometryFiltersSpec.js +++ b/Specs/Core/GeometryFiltersSpec.js @@ -11,7 +11,6 @@ defineSuite([ 'Core/GeographicProjection', 'Core/Geometry', 'Core/GeometryAttribute', - 'Core/GeometryIndices', 'Core/GeometryInstance', 'Core/VertexFormat', 'Core/Math' @@ -27,7 +26,6 @@ defineSuite([ GeographicProjection, Geometry, GeometryAttribute, - GeometryIndices, GeometryInstance, VertexFormat, CesiumMath) { @@ -36,15 +34,13 @@ defineSuite([ it('converts triangles to wireframe in place', function() { var mesh = GeometryFilters.toWireframe(new Geometry({ - indexList : { - values : [0, 1, 2, 3, 4, 5] - }, + indexList : [0, 1, 2, 3, 4, 5], primitiveType : PrimitiveType.TRIANGLES })); expect(mesh.primitiveType).toEqual(PrimitiveType.LINES); - var v = mesh.indexList.values; + var v = mesh.indexList; expect(v.length).toEqual(12); expect(v[0]).toEqual(0); @@ -64,15 +60,13 @@ defineSuite([ it('converts a triangle fan to wireframe in place', function() { var mesh = GeometryFilters.toWireframe(new Geometry({ - indexList : { - values : [0, 1, 2, 3] - }, + indexList : [0, 1, 2, 3], primitiveType : PrimitiveType.TRIANGLE_FAN })); expect(mesh.primitiveType).toEqual(PrimitiveType.LINES); - var v = mesh.indexList.values; + var v = mesh.indexList; expect(v.length).toEqual(12); expect(v[0]).toEqual(0); @@ -92,15 +86,13 @@ defineSuite([ it('converts a triangle strip to wireframe in place', function() { var mesh = GeometryFilters.toWireframe(new Geometry({ - indexList : { - values : [0, 1, 2, 3] - }, + indexList : [0, 1, 2, 3], primitiveType : PrimitiveType.TRIANGLE_STRIP })); expect(mesh.primitiveType).toEqual(PrimitiveType.LINES); - var v = mesh.indexList.values; + var v = mesh.indexList; expect(v.length).toEqual(12); expect(v[0]).toEqual(0); @@ -190,26 +182,24 @@ defineSuite([ values : [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0] }) }, - indexList : { - values : [5, 3, 2, 0, 1, 4, 4, 1, 3, 2, 5, 0] - }, + indexList : [5, 3, 2, 0, 1, 4, 4, 1, 3, 2, 5, 0], primitiveType : PrimitiveType.TRIANGLES }); GeometryFilters.reorderForPreVertexCache(mesh); - expect(mesh.indexList.values[0]).toEqual(0); - expect(mesh.indexList.values[1]).toEqual(1); - expect(mesh.indexList.values[2]).toEqual(2); - expect(mesh.indexList.values[3]).toEqual(3); - expect(mesh.indexList.values[4]).toEqual(4); - expect(mesh.indexList.values[5]).toEqual(5); - expect(mesh.indexList.values[6]).toEqual(5); - expect(mesh.indexList.values[7]).toEqual(4); - expect(mesh.indexList.values[8]).toEqual(1); - expect(mesh.indexList.values[9]).toEqual(2); - expect(mesh.indexList.values[10]).toEqual(0); - expect(mesh.indexList.values[11]).toEqual(3); + expect(mesh.indexList[0]).toEqual(0); + expect(mesh.indexList[1]).toEqual(1); + expect(mesh.indexList[2]).toEqual(2); + expect(mesh.indexList[3]).toEqual(3); + expect(mesh.indexList[4]).toEqual(4); + expect(mesh.indexList[5]).toEqual(5); + expect(mesh.indexList[6]).toEqual(5); + expect(mesh.indexList[7]).toEqual(4); + expect(mesh.indexList[8]).toEqual(1); + expect(mesh.indexList[9]).toEqual(2); + expect(mesh.indexList[10]).toEqual(0); + expect(mesh.indexList[11]).toEqual(3); expect(mesh.attributes.weight.values[0]).toEqual(5.0); expect(mesh.attributes.weight.values[1]).toEqual(3.0); @@ -243,7 +233,7 @@ defineSuite([ ellipsoid : new Ellipsoid(10.0, 10.0, 10.0), numberOfPartitions : 100 }); - var indices = mesh.indexList.values; + var indices = mesh.indexList; var numIndices = indices.length; var maximumIndex = 0; for ( var i = 0; i < numIndices; i++) { @@ -256,7 +246,7 @@ defineSuite([ cacheSize : 24}); expect(ACMRbefore).toBeGreaterThan(1.00); mesh = GeometryFilters.reorderForPostVertexCache(mesh); - indices = mesh.indexList.values; + indices = mesh.indexList; var ACMRafter = Tipsify.calculateACMR({indices : indices, maximumIndex : maximumIndex, cacheSize : 24}); @@ -277,9 +267,7 @@ defineSuite([ values : [1.0] }) }, - indexList : { - values : [0, 0, 0] - }, + indexList : [0, 0, 0], primitiveType : PrimitiveType.TRIANGLES }); @@ -304,9 +292,7 @@ defineSuite([ values : times }) }, - indexList : { - values : [0, 0, 0, sixtyFourK, sixtyFourK, sixtyFourK, 0, sixtyFourK, 0] - }, + indexList : [0, 0, 0, sixtyFourK, sixtyFourK, sixtyFourK, 0, sixtyFourK, 0], primitiveType : PrimitiveType.TRIANGLES }); @@ -318,7 +304,7 @@ defineSuite([ expect(meshes[0].attributes.time.values).toEqual([0, sixtyFourK]); expect(meshes[0].primitiveType).toEqual(PrimitiveType.TRIANGLES); - expect(meshes[0].indexList.values).toEqual([0, 0, 0, 1, 1, 1, 0, 1, 0]); + expect(meshes[0].indexList).toEqual([0, 0, 0, 1, 1, 1, 0, 1, 0]); }); it('fitToUnsignedShortIndices creates two meshes', function() { @@ -343,9 +329,7 @@ defineSuite([ values : positions }) }, - indexList : { - values : indices - }, + indexList : indices, primitiveType : PrimitiveType.TRIANGLES }); @@ -354,10 +338,10 @@ defineSuite([ expect(meshes.length).toEqual(2); expect(meshes[0].attributes.position.values.length).toEqual(positions.length - 6); // Two vertices are not copied (0, 1) - expect(meshes[0].indexList.values.length).toEqual(indices.length - 3); // One triangle is not copied (0, 1, 2) + expect(meshes[0].indexList.length).toEqual(indices.length - 3); // One triangle is not copied (0, 1, 2) expect(meshes[1].attributes.position.values.length).toEqual(9); - expect(meshes[1].indexList.values.length).toEqual(3); + expect(meshes[1].indexList.length).toEqual(3); }); it('fitToUnsignedShortIndices throws without triangles', function() { @@ -369,9 +353,7 @@ defineSuite([ values : [10.0] }) }, - indexList : { - values : [0] - }, + indexList : [0], primitiveType : PrimitiveType.POINTS }); @@ -394,9 +376,7 @@ defineSuite([ values : [1.0, 2.0] }) }, - indexList : { - values : [0, 0, 0] - }, + indexList : [0, 0, 0], primitiveType : PrimitiveType.TRIANGLES }); @@ -534,9 +514,7 @@ defineSuite([ ] }) }, - indexList : new GeometryIndices({ - values : [0, 1, 2] - }), + indexList : [0, 1, 2], primitiveType : PrimitiveType.TRIANGLES }) }); @@ -553,9 +531,7 @@ defineSuite([ ] }) }, - indexList : new GeometryIndices({ - values : [0, 1, 2] - }), + indexList : [0, 1, 2], primitiveType : PrimitiveType.TRIANGLES }) }); @@ -576,9 +552,7 @@ defineSuite([ ]) }) }, - indexList : new GeometryIndices({ - values : new Uint16Array([0, 1, 2, 3, 4, 5]) - }), + indexList : new Uint16Array([0, 1, 2, 3, 4, 5]), primitiveType : PrimitiveType.TRIANGLES })); }); @@ -666,9 +640,7 @@ defineSuite([ componentsPerAttribute: 3 }) }, - indexList : { - values: [0, 1, 2] - }, + indexList : [0, 1, 2], primitiveType: PrimitiveType.TRIANGLE_STRIP }); @@ -686,9 +658,7 @@ defineSuite([ componentsPerAttribute: 3 }) }, - indexList : { - values: [0, 1, 2] - }, + indexList : [0, 1, 2], primitiveType: PrimitiveType.TRIANGLES }); @@ -706,9 +676,7 @@ defineSuite([ componentsPerAttribute: 3 }) }, - indexList : { - values: [0, 1, 2, 1, 3, 2] - }, + indexList : [0, 1, 2, 1, 3, 2], primitiveType: PrimitiveType.TRIANGLES }); @@ -730,9 +698,7 @@ defineSuite([ componentsPerAttribute: 3 }) }, - indexList : { - values: [0, 1, 2, 3, 0, 2, 4, 0, 3, 4, 5, 0, 5, 6, 0, 6, 1, 0] - }, + indexList : [0, 1, 2, 3, 0, 2, 4, 0, 3, 4, 5, 0, 5, 6, 0, 6, 1, 0], primitiveType: PrimitiveType.TRIANGLES }); @@ -984,9 +950,7 @@ defineSuite([ componentsPerAttribute: 2 }) }, - indexList : { - values: [0, 1, 2] - }, + indexList : [0, 1, 2], primitiveType: PrimitiveType.TRIANGLE_STRIP }); @@ -1008,9 +972,7 @@ defineSuite([ componentsPerAttribute: 2 }) }, - indexList : { - values: [0, 1, 2] - }, + indexList : [0, 1, 2], primitiveType: PrimitiveType.TRIANGLES }); @@ -1033,9 +995,7 @@ defineSuite([ componentsPerAttribute: 2 }) }, - indexList : { - values: [0, 1, 2, 1, 3, 2] - }, + indexList : [0, 1, 2, 1, 3, 2], primitiveType: PrimitiveType.TRIANGLES }); diff --git a/Specs/Core/PolygonGeometrySpec.js b/Specs/Core/PolygonGeometrySpec.js index a43c1a608031..1d0c5bc6a02f 100644 --- a/Specs/Core/PolygonGeometrySpec.js +++ b/Specs/Core/PolygonGeometrySpec.js @@ -93,7 +93,7 @@ defineSuite([ }); expect(p.attributes.position.values.length).toEqual(3 * 11); - expect(p.indexList.values.length).toEqual(3 * 14); + expect(p.indexList.length).toEqual(3 * 14); }); it('computes all attributes', function() { @@ -113,7 +113,7 @@ defineSuite([ expect(p.attributes.normal.values.length).toEqual(3 * 11); expect(p.attributes.tangent.values.length).toEqual(3 * 11); expect(p.attributes.binormal.values.length).toEqual(3 * 11); - expect(p.indexList.values.length).toEqual(3 * 14); + expect(p.indexList.length).toEqual(3 * 14); }); it('creates a polygon from hierarchy', function() { @@ -149,7 +149,7 @@ defineSuite([ }); expect(p.attributes.position.values.length).toEqual(3 * 14); - expect(p.indexList.values.length).toEqual(3 * 10); + expect(p.indexList.length).toEqual(3 * 10); }); it('creates a polygon from clockwise hierarchy', function() { @@ -185,7 +185,7 @@ defineSuite([ }); expect(p.attributes.position.values.length).toEqual(3 * 14); - expect(p.indexList.values.length).toEqual(3 * 10); + expect(p.indexList.length).toEqual(3 * 10); }); }, 'WebGL'); diff --git a/Specs/Core/PolygonPipelineSpec.js b/Specs/Core/PolygonPipelineSpec.js index 0951b0fbcd0f..21828353e419 100644 --- a/Specs/Core/PolygonPipelineSpec.js +++ b/Specs/Core/PolygonPipelineSpec.js @@ -360,9 +360,9 @@ defineSuite([ expect(subdivision.attributes.position.values[7]).toEqual(0.0); expect(subdivision.attributes.position.values[8]).toEqual(0.0); - expect(subdivision.indexList.values[0]).toEqual(0); - expect(subdivision.indexList.values[1]).toEqual(1); - expect(subdivision.indexList.values[2]).toEqual(2); + expect(subdivision.indexList[0]).toEqual(0); + expect(subdivision.indexList[1]).toEqual(1); + expect(subdivision.indexList[2]).toEqual(2); }); it('eliminateHoles throws an exception without an outerRing', function() { diff --git a/Specs/Core/WallGeometrySpec.js b/Specs/Core/WallGeometrySpec.js index 70197b6d10cc..1f45c2b8064f 100644 --- a/Specs/Core/WallGeometrySpec.js +++ b/Specs/Core/WallGeometrySpec.js @@ -42,7 +42,7 @@ defineSuite([ }); expect(w.attributes.position.values.length).toEqual(2 * 2 * 3); - expect(w.indexList.values.length).toEqual(2 * 3); + expect(w.indexList.length).toEqual(2 * 3); }); it('creates positions relative to terrain', function() { @@ -63,7 +63,7 @@ defineSuite([ }); expect(w.attributes.position.values.length).toEqual(2 * 2 * 3); - expect(w.indexList.values.length).toEqual(2 * 3); + expect(w.indexList.length).toEqual(2 * 3); }); it('creates all attributes', function() { @@ -83,7 +83,7 @@ defineSuite([ expect(w.attributes.tangent.values.length).toEqual(3 * 2 * 3); expect(w.attributes.binormal.values.length).toEqual(3 * 2 * 3); expect(w.attributes.st.values.length).toEqual(3 * 2 * 2); - expect(w.indexList.values.length).toEqual((3 * 2 - 2) * 3); + expect(w.indexList.length).toEqual((3 * 2 - 2) * 3); }); }); diff --git a/Specs/Renderer/VertexArrayFactorySpec.js b/Specs/Renderer/VertexArrayFactorySpec.js index 0763859acc96..d357d0616036 100644 --- a/Specs/Renderer/VertexArrayFactorySpec.js +++ b/Specs/Renderer/VertexArrayFactorySpec.js @@ -3,6 +3,8 @@ defineSuite([ 'Specs/createContext', 'Specs/destroyContext', 'Core/ComponentDatatype', + 'Core/Geometry', + 'Core/GeometryAttribute', 'Core/GeometryFilters', 'Core/PrimitiveType', 'Core/IndexDatatype', @@ -13,6 +15,8 @@ defineSuite([ createContext, destroyContext, ComponentDatatype, + Geometry, + GeometryAttribute, GeometryFilters, PrimitiveType, IndexDatatype, @@ -54,15 +58,15 @@ defineSuite([ }); it('creates a single-attribute vertex (non-interleaved)', function() { - var mesh = { + var mesh = new Geometry({ attributes : { - position : { + position : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 3, values : [0.0, 0.0, 0.0, 1.0, 1.0, 1.0] - } + }) } - }; + }); var va = context.createVertexArrayFromMesh({ mesh : mesh, @@ -83,15 +87,15 @@ defineSuite([ }); it('creates a single-attribute vertex (interleaved)', function() { - var mesh = { + var mesh = new Geometry({ attributes : { - position : { + position : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 3, values : [0.0, 0.0, 0.0, 1.0, 1.0, 1.0] - } + }) } - }; + }); var va = context.createVertexArrayFromMesh({ mesh : mesh, @@ -114,20 +118,20 @@ defineSuite([ }); it('creates a homogeneous multiple-attribute vertex (non-interleaved)', function() { - var mesh = { + var mesh = new Geometry({ attributes : { - position : { + position : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 3, values : [0.0, 0.0, 0.0, 2.0, 2.0, 2.0] - }, - normal : { + }), + normal : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 3, values : [1.0, 1.0, 1.0, 3.0, 3.0, 3.0] - } + }) } - }; + }); var va = context.createVertexArrayFromMesh({ mesh : mesh, @@ -155,20 +159,20 @@ defineSuite([ }); it('creates a homogeneous multiple-attribute vertex (interleaved)', function() { - var mesh = { + var mesh = new Geometry({ attributes : { - position : { + position : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 3, values : [0.0, 0.0, 0.0, 2.0, 2.0, 2.0] - }, - normal : { + }), + normal : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 3, values : [1.0, 1.0, 1.0, 3.0, 3.0, 3.0] - } + }) } - }; + }); var va = context.createVertexArrayFromMesh({ mesh : mesh, @@ -199,20 +203,20 @@ defineSuite([ }); it('creates a heterogeneous multiple-attribute vertex (interleaved)', function() { - var mesh = { + var mesh = new Geometry({ attributes : { - position : { + position : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 3, values : [0.0, 0.0, 0.0, 2.0, 2.0, 2.0] - }, - colors : { + }), + colors : new GeometryAttribute({ componentDatatype : ComponentDatatype.UNSIGNED_BYTE, componentsPerAttribute : 4, values : [1, 1, 1, 1, 2, 2, 2, 2] - } + }) } - }; + }); var va = context.createVertexArrayFromMesh({ mesh : mesh, @@ -243,25 +247,25 @@ defineSuite([ }); it('sorts interleaved attributes from large to small components', function() { - var mesh = { + var mesh = new Geometry({ attributes : { - bytes : { + bytes : new GeometryAttribute({ componentDatatype : ComponentDatatype.BYTE, componentsPerAttribute : 1, values : [0] - }, - shorts : { + }), + shorts : new GeometryAttribute({ componentDatatype : ComponentDatatype.SHORT, componentsPerAttribute : 1, values : [1] - }, - floats : { + }), + floats : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 1, values : [2] - } + }) } - }; + }); var attributeIndices = GeometryFilters.createAttributeIndices(mesh); var va = context.createVertexArrayFromMesh({ @@ -308,20 +312,20 @@ defineSuite([ it('sorts interleaved attributes from large to small components (2)', function() { // TODO: Color should be normalized - var mesh = { + var mesh = new Geometry({ attributes : { - color : { + color : new GeometryAttribute({ componentDatatype : ComponentDatatype.UNSIGNED_BYTE, componentsPerAttribute : 4, values : [255, 0, 0, 255, 0, 255, 0, 255] - }, - position : { + }), + position : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 3, values : [0.0, 0.0, 0.0, 0.0, 0.0, 0.0] - } + }) } - }; + }); var attributeIndices = GeometryFilters.createAttributeIndices(mesh); var va = context.createVertexArrayFromMesh({ @@ -372,30 +376,30 @@ defineSuite([ }); it('sorts interleaved attributes from large to small components (3)', function() { - var mesh = { + var mesh = new Geometry({ attributes : { - unsignedByteAttribute : { + unsignedByteAttribute : new GeometryAttribute({ componentDatatype : ComponentDatatype.UNSIGNED_BYTE, componentsPerAttribute : 2, values : [1, 2] - }, - unsignedShortAttribute : { + }), + unsignedShortAttribute : new GeometryAttribute({ componentDatatype : ComponentDatatype.UNSIGNED_SHORT, componentsPerAttribute : 1, values : [3] - }, - byteAttribute : { + }), + byteAttribute : new GeometryAttribute({ componentDatatype : ComponentDatatype.BYTE, componentsPerAttribute : 1, values : [4] - }, - shortAttribute : { + }), + shortAttribute : new GeometryAttribute({ componentDatatype : ComponentDatatype.SHORT, componentsPerAttribute : 1, values : [5] - } + }) } - }; + }); var attributeIndices = GeometryFilters.createAttributeIndices(mesh); var va = context.createVertexArrayFromMesh({ @@ -440,30 +444,30 @@ defineSuite([ it('creates a custom interleaved vertex', function() { // TODO: Color should be normalized - var mesh = { + var mesh = new Geometry({ attributes : { - position : { + position : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 3, values : [0.0, 0.0, 0.0, 0.0, 0.0, 0.0] - }, - color : { + }), + color : new GeometryAttribute({ componentDatatype : ComponentDatatype.UNSIGNED_BYTE, componentsPerAttribute : 3, values : [255, 0, 0, 0, 255, 0] - }, - normal : { + }), + normal : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 3, values : [1.0, 0.0, 0.0, 0.0, 1.0, 0.0] - }, - temperature : { + }), + temperature : new GeometryAttribute({ componentDatatype : ComponentDatatype.UNSIGNED_SHORT, componentsPerAttribute : 1, values : [75, 100] - } + }) } - }; + }); var attributeIndices = GeometryFilters.createAttributeIndices(mesh); var va = context.createVertexArrayFromMesh({ @@ -540,12 +544,10 @@ defineSuite([ }); it('creates an index buffer', function() { - var mesh = { - indexList : { - primitiveType : PrimitiveType.POINTS, - values : [0] - } - }; + var mesh = new Geometry({ + indexList : [0], + primitiveType : PrimitiveType.POINTS + }); var va = context.createVertexArrayFromMesh({ mesh : mesh @@ -555,24 +557,24 @@ defineSuite([ expect(va.getIndexBuffer()).toBeDefined(); expect(va.getIndexBuffer().getUsage()).toEqual(BufferUsage.DYNAMIC_DRAW); // Default expect(va.getIndexBuffer().getIndexDatatype()).toEqual(IndexDatatype.UNSIGNED_SHORT); - expect(va.getIndexBuffer().getNumberOfIndices()).toEqual(mesh.indexList.values.length); + expect(va.getIndexBuffer().getNumberOfIndices()).toEqual(mesh.indexList.length); }); it('throws with different number of interleaved attributes', function() { - var mesh = { + var mesh = new Geometry({ attributes : { - position : { + position : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 1, values : [0.0] - }, - normal : { + }), + normal : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 1, values : [1.0, 2.0] - } + }) } - }; + }); expect(function() { return context.createVertexArrayFromMesh({ @@ -583,20 +585,20 @@ defineSuite([ }); it('throws with duplicate indices', function() { - var mesh = { + var mesh = new Geometry({ attributes : { - position : { + position : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 1, values : [0.0] - }, - normal : { + }), + normal : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 1, values : [1.0] - } + }) } - }; + }); expect(function() { return context.createVertexArrayFromMesh({ From ccf1c6a7ae4d6ef0df4bb3ff3cd5e8896bcf8a9b Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Thu, 6 Jun 2013 08:19:42 -0400 Subject: [PATCH 144/306] Renamed meshes to geometries --- Source/Core/GeometryFilters.js | 14 ++++++------ Source/Core/PolygonGeometry.js | 8 +++---- Source/Scene/Polygon.js | 22 +++++++++---------- Source/Scene/Primitive.js | 1 + Specs/Core/GeometryFiltersSpec.js | 36 +++++++++++++++---------------- 5 files changed, 41 insertions(+), 40 deletions(-) diff --git a/Source/Core/GeometryFilters.js b/Source/Core/GeometryFilters.js index 391e70add8ea..d2ecacc82c4d 100644 --- a/Source/Core/GeometryFilters.js +++ b/Source/Core/GeometryFilters.js @@ -341,7 +341,7 @@ define([ }); } - var meshes = []; + var geometries = []; if (typeof mesh !== 'undefined') { if (mesh.primitiveType !== PrimitiveType.TRIANGLES) { @@ -398,7 +398,7 @@ define([ newIndices.push(i2); if (currentIndex + 3 > sixtyFourK) { - meshes.push(createMesh(newAttributes, mesh.primitiveType, newIndices)); + geometries.push(createMesh(newAttributes, mesh.primitiveType, newIndices)); // Reset for next vertex-array oldToNewIndex = []; @@ -409,15 +409,15 @@ define([ } if (newIndices.length !== 0) { - meshes.push(createMesh(newAttributes, mesh.primitiveType, newIndices)); + geometries.push(createMesh(newAttributes, mesh.primitiveType, newIndices)); } } else { - // No need to split into multiple meshes - meshes.push(mesh); + // No need to split into multiple geometries + geometries.push(mesh); } } - return meshes; + return geometries; }; /** @@ -775,7 +775,7 @@ define([ for (i = 0; i < length; ++i) { var bs = instances[i].geometry.boundingSphere; if (typeof bs === 'undefined') { - // If any meshes have an undefined bounding sphere, then so does the combined mesh + // If any geometries have an undefined bounding sphere, then so does the combined mesh boundingSphere = undefined; break; } diff --git a/Source/Core/PolygonGeometry.js b/Source/Core/PolygonGeometry.js index a623121b55ec..687e011baec8 100644 --- a/Source/Core/PolygonGeometry.js +++ b/Source/Core/PolygonGeometry.js @@ -207,7 +207,7 @@ define([ var positions = options.positions; var polygonHierarchy = options.polygonHierarchy; - var meshes = []; + var geometries = []; var mesh; var boundingSphere; var i; @@ -221,7 +221,7 @@ define([ boundingSphere = BoundingSphere.fromPoints(positions); mesh = createMeshFromPositions(ellipsoid, positions, boundingSphere, granularity); if (typeof mesh !== 'undefined') { - meshes.push(mesh); + geometries.push(mesh); } } else if (typeof polygonHierarchy !== 'undefined') { // create from a polygon hierarchy @@ -274,14 +274,14 @@ define([ for (i = 0; i < polygonHierarchy.length; i++) { mesh = createMeshFromPositions(ellipsoid, polygonHierarchy[i], boundingSphere, granularity); if (typeof mesh !== 'undefined') { - meshes.push(mesh); + geometries.push(mesh); } } } else { throw new DeveloperError('positions or hierarchy must be supplied.'); } - mesh = GeometryFilters.combine(meshes); + mesh = GeometryFilters.combine(geometries); mesh = PolygonPipeline.scaleToGeodeticHeight(mesh, height, ellipsoid); var attributes = {}; diff --git a/Source/Scene/Polygon.js b/Source/Scene/Polygon.js index 66fc76128730..9c8a4c211967 100644 --- a/Source/Scene/Polygon.js +++ b/Source/Scene/Polygon.js @@ -87,17 +87,17 @@ define([ return this._va; }; - PositionVertices.prototype.update = function(context, meshes, bufferUsage) { - if (typeof meshes !== 'undefined') { + PositionVertices.prototype.update = function(context, geometries, bufferUsage) { + if (typeof geometries !== 'undefined') { // Initially create or recreate vertex array and buffers this._destroyVA(); var va = []; - var length = meshes.length; + var length = geometries.length; for ( var i = 0; i < length; ++i) { va.push(context.createVertexArrayFromMesh({ - mesh : meshes[i], + mesh : geometries[i], attributeIndices : attributeIndices, bufferUsage : bufferUsage, vertexLayout : VertexLayout.INTERLEAVED @@ -526,17 +526,17 @@ define([ }); } - function createMeshes(polygon) { + function createGeometries(polygon) { // PERFORMANCE_IDEA: Move this to a web-worker. var i; - var meshes = []; + var geometries = []; var mesh; if (typeof polygon._positions !== 'undefined') { polygon._boundingVolume = BoundingSphere.fromPoints(polygon._positions, polygon._boundingVolume); mesh = createMeshFromPositions(polygon, polygon._positions, polygon._textureRotationAngle, polygon._boundingVolume); if (typeof mesh !== 'undefined') { - meshes.push(mesh); + geometries.push(mesh); } } else if (typeof polygon._polygonHierarchy !== 'undefined') { var outerPositions = polygon._polygonHierarchy[0]; @@ -547,16 +547,16 @@ define([ for (i = 0; i < polygon._polygonHierarchy.length; i++) { mesh = createMeshFromPositions(polygon, polygon._polygonHierarchy[i], polygon._textureRotationAngle, polygon._boundingVolume, outerPositions); if (typeof mesh !== 'undefined') { - meshes.push(mesh); + geometries.push(mesh); } } } - if (meshes.length === 0) { + if (geometries.length === 0) { return undefined; } - mesh = GeometryFilters.combine(meshes); + mesh = GeometryFilters.combine(geometries); mesh = PolygonPipeline.scaleToGeodeticHeight(mesh, polygon.height, polygon.ellipsoid); mesh = GeometryFilters.reorderForPostVertexCache(mesh); mesh = GeometryFilters.reorderForPreVertexCache(mesh); @@ -665,7 +665,7 @@ define([ if (this._createVertexArray) { this._createVertexArray = false; - this._vertices.update(context, createMeshes(this), this.bufferUsage); + this._vertices.update(context, createGeometries(this), this.bufferUsage); } if (typeof this._vertices.getVertexArrays() === 'undefined') { diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index d87bfe915f2f..8ba00501b3e1 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -284,6 +284,7 @@ define([ } } + // PERFORMANCE_IDEA: Move pipeline to a web-worker. function geometryPipeline(primitive, instances, context) { // Copy instances first since most pipeline operations modify the geometry and instance in-place. var length = instances.length; diff --git a/Specs/Core/GeometryFiltersSpec.js b/Specs/Core/GeometryFiltersSpec.js index cc7e9967cd35..e88158896f59 100644 --- a/Specs/Core/GeometryFiltersSpec.js +++ b/Specs/Core/GeometryFiltersSpec.js @@ -271,10 +271,10 @@ defineSuite([ primitiveType : PrimitiveType.TRIANGLES }); - var meshes = GeometryFilters.fitToUnsignedShortIndices(mesh); + var geometries = GeometryFilters.fitToUnsignedShortIndices(mesh); - expect(meshes.length).toEqual(1); - expect(meshes[0]).toBe(mesh); + expect(geometries.length).toEqual(1); + expect(geometries[0]).toBe(mesh); }); it('fitToUnsignedShortIndices creates one mesh', function() { @@ -296,18 +296,18 @@ defineSuite([ primitiveType : PrimitiveType.TRIANGLES }); - var meshes = GeometryFilters.fitToUnsignedShortIndices(mesh); + var geometries = GeometryFilters.fitToUnsignedShortIndices(mesh); - expect(meshes.length).toEqual(1); - expect(meshes[0].attributes.time.componentDatatype).toEqual(ComponentDatatype.FLOAT); - expect(meshes[0].attributes.time.componentsPerAttribute).toEqual(1); - expect(meshes[0].attributes.time.values).toEqual([0, sixtyFourK]); + expect(geometries.length).toEqual(1); + expect(geometries[0].attributes.time.componentDatatype).toEqual(ComponentDatatype.FLOAT); + expect(geometries[0].attributes.time.componentsPerAttribute).toEqual(1); + expect(geometries[0].attributes.time.values).toEqual([0, sixtyFourK]); - expect(meshes[0].primitiveType).toEqual(PrimitiveType.TRIANGLES); - expect(meshes[0].indexList).toEqual([0, 0, 0, 1, 1, 1, 0, 1, 0]); + expect(geometries[0].primitiveType).toEqual(PrimitiveType.TRIANGLES); + expect(geometries[0].indexList).toEqual([0, 0, 0, 1, 1, 1, 0, 1, 0]); }); - it('fitToUnsignedShortIndices creates two meshes', function() { + it('fitToUnsignedShortIndices creates two geometries', function() { var sixtyFourK = 64 * 1024; var positions = []; @@ -333,15 +333,15 @@ defineSuite([ primitiveType : PrimitiveType.TRIANGLES }); - var meshes = GeometryFilters.fitToUnsignedShortIndices(mesh); + var geometries = GeometryFilters.fitToUnsignedShortIndices(mesh); - expect(meshes.length).toEqual(2); + expect(geometries.length).toEqual(2); - expect(meshes[0].attributes.position.values.length).toEqual(positions.length - 6); // Two vertices are not copied (0, 1) - expect(meshes[0].indexList.length).toEqual(indices.length - 3); // One triangle is not copied (0, 1, 2) + expect(geometries[0].attributes.position.values.length).toEqual(positions.length - 6); // Two vertices are not copied (0, 1) + expect(geometries[0].indexList.length).toEqual(indices.length - 3); // One triangle is not copied (0, 1, 2) - expect(meshes[1].attributes.position.values.length).toEqual(9); - expect(meshes[1].indexList.length).toEqual(3); + expect(geometries[1].attributes.position.values.length).toEqual(9); + expect(geometries[1].indexList.length).toEqual(3); }); it('fitToUnsignedShortIndices throws without triangles', function() { @@ -491,7 +491,7 @@ defineSuite([ expect(combined).toBe(instance.geometry); }); - it('GeometryFilters.combine combines several meshes', function() { + it('GeometryFilters.combine combines several geometries', function() { var instance = new GeometryInstance({ geometry : new Geometry({ attributes : { From 4a8625bea52366c1fe20166f736e7c06498bcc08 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Thu, 6 Jun 2013 08:34:33 -0400 Subject: [PATCH 145/306] Start of renaming Mesh to Geometry --- Apps/Sandcastle/gallery/Custom Rendering.html | 4 +-- CHANGES.md | 1 + Source/Core/GeometryFilters.js | 33 ++++++++++--------- Source/Core/PolygonGeometry.js | 12 +++---- Source/Renderer/Context.js | 8 ++--- Source/Renderer/VertexArray.js | 2 +- Source/Renderer/VertexLayout.js | 2 +- Source/Scene/CentralBody.js | 6 ++-- Source/Scene/CentralBodySurface.js | 2 +- Source/Scene/EllipsoidPrimitive.js | 2 +- Source/Scene/ImageryLayer.js | 6 ++-- Source/Scene/Polygon.js | 16 ++++----- Source/Scene/Primitive.js | 2 +- Source/Scene/SkyAtmosphere.js | 2 +- Source/Scene/SkyBox.js | 2 +- Source/Scene/SunPostProcess.js | 2 +- Source/Scene/ViewportQuad.js | 2 +- Specs/Renderer/VertexArrayFactorySpec.js | 28 ++++++++-------- Specs/Scene/MultifrustumSpec.js | 2 +- 19 files changed, 68 insertions(+), 66 deletions(-) diff --git a/Apps/Sandcastle/gallery/Custom Rendering.html b/Apps/Sandcastle/gallery/Custom Rendering.html index d25008d3b030..3920f7327df1 100644 --- a/Apps/Sandcastle/gallery/Custom Rendering.html +++ b/Apps/Sandcastle/gallery/Custom Rendering.html @@ -102,7 +102,7 @@ })); var attributeIndices = Cesium.GeometryFilters.createAttributeIndices(mesh); - colorCommand.vertexArray = pickCommand.vertexArray = context.createVertexArrayFromMesh({ + colorCommand.vertexArray = pickCommand.vertexArray = context.createVertexArrayFromGeometry({ mesh : mesh, attributeIndices : attributeIndices, bufferUsage : Cesium.BufferUsage.STATIC_DRAW @@ -261,7 +261,7 @@ } colorCommand.vertexArray = colorCommand.vertexArray && colorCommand.vertexArray.destroy(); - colorCommand.vertexArray = pickCommand.vertexArray = context.createVertexArrayFromMesh({ + colorCommand.vertexArray = pickCommand.vertexArray = context.createVertexArrayFromGeometry({ mesh : mesh, attributeIndices : this._attributeIndices, bufferUsage : Cesium.BufferUsage.STATIC_DRAW diff --git a/CHANGES.md b/CHANGES.md index 15ad63c01f06..d0d076e66e4a 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -19,6 +19,7 @@ Beta Releases * Removed `PlaneTessellator`. It was incomplete and not used. * Renamed `MeshFilters` to `GeometryFilters`. * Renamed `MeshFilters.toWireframeInPlace` to `GeometryFilters.toWireframe`. + * Renamed `Context.createVertexArrayFromMesh` to `Context.createVertexArrayFromGeometry`. * Renamed `ComponentDatatype.*.toTypedArray` to `ComponentDatatype.*.createTypedArray`. * Replaced `Uniform.getFrameNumber` and `Uniform.getTime` with `Uniform.getFrameState`, which returns the full frame state. * Removed `Polygon.configureExtent`. diff --git a/Source/Core/GeometryFilters.js b/Source/Core/GeometryFilters.js index d2ecacc82c4d..ae6a01e224a5 100644 --- a/Source/Core/GeometryFilters.js +++ b/Source/Core/GeometryFilters.js @@ -36,7 +36,7 @@ define([ * * @exports GeometryFilters * - * @see Context#createVertexArrayFromMesh + * @see Context#createVertexArrayFromGeometry */ var GeometryFilters = {}; @@ -257,9 +257,9 @@ define([ * @param {Geometry} mesh The mesh to filter, which is modified in place. * @param {Number} [cacheCapacity=24] The number of vertices that can be held in the GPU's vertex cache. * - * @exception {DeveloperError} Mesh's index list must be defined. - * @exception {DeveloperError} Mesh's index lists' lengths must each be a multiple of three. - * @exception {DeveloperError} Mesh's index list's maximum index value must be greater than zero. + * @exception {DeveloperError} Geometry's index list must be defined. + * @exception {DeveloperError} Geometry's index lists' lengths must each be a multiple of three. + * @exception {DeveloperError} Geometry's index list's maximum index value must be greater than zero. * @exception {DeveloperError} cacheCapacity must be greater than two. * * @returns The modified mesh argument, with its indices optimally reordered for the post-vertex-shader cache. @@ -332,15 +332,6 @@ define([ * @exception {DeveloperError} All mesh attribute lists must have the same number of attributes. */ GeometryFilters.fitToUnsignedShortIndices = function(mesh) { - function createMesh(attributes, primitiveType, indices) { - // TODO: is this always what we want, for say BoxGeometry? - return new Geometry({ - attributes : attributes, - indexList : indices, - primitiveType : primitiveType - }); - } - var geometries = []; if (typeof mesh !== 'undefined') { @@ -398,7 +389,12 @@ define([ newIndices.push(i2); if (currentIndex + 3 > sixtyFourK) { - geometries.push(createMesh(newAttributes, mesh.primitiveType, newIndices)); + // TODO: is this always what we want, for say BoxGeometry? + geometries.push(new Geometry({ + attributes : newAttributes, + indexList : newIndices, + primitiveType : mesh.primitiveType + })); // Reset for next vertex-array oldToNewIndex = []; @@ -409,7 +405,12 @@ define([ } if (newIndices.length !== 0) { - geometries.push(createMesh(newAttributes, mesh.primitiveType, newIndices)); + // TODO: is this always what we want, for say BoxGeometry? + geometries.push(new Geometry({ + attributes : newAttributes, + indexList : newIndices, + primitiveType : mesh.primitiveType + })); } } else { // No need to split into multiple geometries @@ -685,7 +686,7 @@ define([ var sourceValues; var sourceValuesLength; - // PERFORMANCE_IDEA: Interleave here instead of createVertexArrayFromMesh to save a copy. + // PERFORMANCE_IDEA: Interleave here instead of createVertexArrayFromGeometry to save a copy. // This will require adding offset and stride to the mesh. // Combine attributes from each mesh into a single typed array diff --git a/Source/Core/PolygonGeometry.js b/Source/Core/PolygonGeometry.js index 687e011baec8..72eb36d3cc5f 100644 --- a/Source/Core/PolygonGeometry.js +++ b/Source/Core/PolygonGeometry.js @@ -87,9 +87,9 @@ define([ return result; } - var createMeshFromPositionsPositions = []; + var createGeometryFromPositionsPositions = []; - function createMeshFromPositions(ellipsoid, positions, boundingSphere, granularity) { + function createGeometryFromPositions(ellipsoid, positions, boundingSphere, granularity) { var cleanedPositions = PolygonPipeline.cleanUp(positions); if (cleanedPositions.length < 3) { // Duplicate positions result in not enough positions to form a polygon. @@ -97,7 +97,7 @@ define([ } var tangentPlane = EllipsoidTangentPlane.fromPoints(cleanedPositions, ellipsoid); - var positions2D = tangentPlane.projectPointsOntoPlane(cleanedPositions, createMeshFromPositionsPositions); + var positions2D = tangentPlane.projectPointsOntoPlane(cleanedPositions, createGeometryFromPositionsPositions); var originalWindingOrder = PolygonPipeline.computeWindingOrder2D(positions2D); if (originalWindingOrder === WindingOrder.CLOCKWISE) { @@ -219,7 +219,7 @@ define([ outerPositions = positions; boundingSphere = BoundingSphere.fromPoints(positions); - mesh = createMeshFromPositions(ellipsoid, positions, boundingSphere, granularity); + mesh = createGeometryFromPositions(ellipsoid, positions, boundingSphere, granularity); if (typeof mesh !== 'undefined') { geometries.push(mesh); } @@ -272,7 +272,7 @@ define([ boundingSphere = BoundingSphere.fromPoints(outerPositions); for (i = 0; i < polygonHierarchy.length; i++) { - mesh = createMeshFromPositions(ellipsoid, polygonHierarchy[i], boundingSphere, granularity); + mesh = createGeometryFromPositions(ellipsoid, polygonHierarchy[i], boundingSphere, granularity); if (typeof mesh !== 'undefined') { geometries.push(mesh); } @@ -292,7 +292,7 @@ define([ if (vertexFormat.st || vertexFormat.normal || vertexFormat.tangent || vertexFormat.binormal) { // PERFORMANCE_IDEA: Compute before subdivision, then just interpolate during subdivision. - // PERFORMANCE_IDEA: Compute with createMeshFromPositions() for fast path when there's no holes. + // PERFORMANCE_IDEA: Compute with createGeometryFromPositions() for fast path when there's no holes. var cleanedPositions = PolygonPipeline.cleanUp(outerPositions); var tangentPlane = EllipsoidTangentPlane.fromPoints(cleanedPositions, ellipsoid); var boundingRectangle = computeBoundingRectangle(tangentPlane, outerPositions, stRotation, scratchBoundingRectangle); diff --git a/Source/Renderer/Context.js b/Source/Renderer/Context.js index 644e38d09920..03d6711c7c3b 100644 --- a/Source/Renderer/Context.js +++ b/Source/Renderer/Context.js @@ -1138,7 +1138,7 @@ define([ * @exception {DeveloperError} Attribute must have a strideInBytes less than or equal to 255 or not specify it. * @exception {DeveloperError} Index n is used by more than one attribute. * - * @see Context#createVertexArrayFromMesh + * @see Context#createVertexArrayFromGeometry * @see Context#createVertexBuffer * @see Context#createIndexBuffer * @see Context#draw @@ -2321,7 +2321,7 @@ define([ * // usage is used for the created vertex and index buffer. The attributes are not * // interleaved by default. * var mesh = new BoxGeometry(); - * var va = context.createVertexArrayFromMesh({ + * var va = context.createVertexArrayFromGeometry({ * mesh : mesh, * attributeIndices : GeometryFilters.createAttributeIndices(mesh), * }); @@ -2330,7 +2330,7 @@ define([ * * // Example 2. Creates a vertex array with interleaved attributes in a * // single vertex buffer. The vertex and index buffer have static draw usage. - * var va = context.createVertexArrayFromMesh({ + * var va = context.createVertexArrayFromGeometry({ * mesh : mesh, * attributeIndices : GeometryFilters.createAttributeIndices(mesh), * bufferUsage : BufferUsage.STATIC_DRAW, @@ -2343,7 +2343,7 @@ define([ * // attached vertex buffer(s) and index buffer. * va = va.destroy(); */ - Context.prototype.createVertexArrayFromMesh = function(creationArguments) { + Context.prototype.createVertexArrayFromGeometry = function(creationArguments) { var ca = defaultValue(creationArguments, defaultValue.EMPTY_OBJECT); var mesh = defaultValue(ca.mesh, defaultValue.EMPTY_OBJECT); diff --git a/Source/Renderer/VertexArray.js b/Source/Renderer/VertexArray.js index 7527067af2fe..d7834a8a2fff 100644 --- a/Source/Renderer/VertexArray.js +++ b/Source/Renderer/VertexArray.js @@ -122,7 +122,7 @@ define([ * @internalConstructor * * @see {@link Context#createVertexArray} - * @see {@link Context#createVertexArrayFromMesh} + * @see {@link Context#createVertexArrayFromGeometry} */ var VertexArray = function(gl, vertexArrayObject, attributes, indexBuffer) { var vaAttributes = []; diff --git a/Source/Renderer/VertexLayout.js b/Source/Renderer/VertexLayout.js index 853e68181f48..53930b8f4c27 100644 --- a/Source/Renderer/VertexLayout.js +++ b/Source/Renderer/VertexLayout.js @@ -7,7 +7,7 @@ define(['../Core/Enumeration'], function(Enumeration) { * * @exports VertexLayout * - * @see Context#createVertexArrayFromMesh + * @see Context#createVertexArrayFromGeometry */ var VertexLayout = { /** diff --git a/Source/Scene/CentralBody.js b/Source/Scene/CentralBody.js index ee17ff90272e..a4142acf1226 100644 --- a/Source/Scene/CentralBody.js +++ b/Source/Scene/CentralBody.js @@ -370,7 +370,7 @@ define([ } } }; - centralBody._northPoleCommand.vertexArray = context.createVertexArrayFromMesh({ + centralBody._northPoleCommand.vertexArray = context.createVertexArrayFromGeometry({ mesh : mesh, attributeIndices : { position : 0 @@ -418,7 +418,7 @@ define([ } } }; - centralBody._southPoleCommand.vertexArray = context.createVertexArrayFromMesh({ + centralBody._southPoleCommand.vertexArray = context.createVertexArrayFromGeometry({ mesh : mesh, attributeIndices : { position : 0 @@ -552,7 +552,7 @@ define([ indexList : [0, 1, 2, 2, 1, 3], primitiveType : PrimitiveType.TRIANGLES }; - this._depthCommand.vertexArray = context.createVertexArrayFromMesh({ + this._depthCommand.vertexArray = context.createVertexArrayFromGeometry({ mesh : mesh, attributeIndices : { position : 0 diff --git a/Source/Scene/CentralBodySurface.js b/Source/Scene/CentralBodySurface.js index 91923b1a611e..6c1b200c40ac 100644 --- a/Source/Scene/CentralBodySurface.js +++ b/Source/Scene/CentralBodySurface.js @@ -701,7 +701,7 @@ define([ numberOfPartitions : 10 }); GeometryFilters.toWireframe(sphere); - surface._debug.boundingSphereVA = context.createVertexArrayFromMesh({ + surface._debug.boundingSphereVA = context.createVertexArrayFromGeometry({ mesh : sphere, attributeIndices : GeometryFilters.createAttributeIndices(sphere) }); diff --git a/Source/Scene/EllipsoidPrimitive.js b/Source/Scene/EllipsoidPrimitive.js index bde79f4a1622..9b8b23211276 100644 --- a/Source/Scene/EllipsoidPrimitive.js +++ b/Source/Scene/EllipsoidPrimitive.js @@ -200,7 +200,7 @@ define([ dimensions : new Cartesian3(2.0, 2.0, 2.0) }); - vertexArray = context.createVertexArrayFromMesh({ + vertexArray = context.createVertexArrayFromGeometry({ mesh: mesh, attributeIndices: attributeIndices, bufferUsage: BufferUsage.STATIC_DRAW diff --git a/Source/Scene/ImageryLayer.js b/Source/Scene/ImageryLayer.js index cc46d5200ff5..4f3f1720b357 100644 --- a/Source/Scene/ImageryLayer.js +++ b/Source/Scene/ImageryLayer.js @@ -799,7 +799,7 @@ define([ } } - var reprojectMesh = new Geometry({ + var reprojectGeometry = new Geometry({ attributes : { position : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, @@ -815,8 +815,8 @@ define([ position : 0 }; - reproject.vertexArray = context.createVertexArrayFromMesh({ - mesh : reprojectMesh, + reproject.vertexArray = context.createVertexArrayFromGeometry({ + mesh : reprojectGeometry, attributeIndices : reprojectAttribInds, bufferUsage : BufferUsage.STATIC_DRAW }); diff --git a/Source/Scene/Polygon.js b/Source/Scene/Polygon.js index 9c8a4c211967..0e20c265f555 100644 --- a/Source/Scene/Polygon.js +++ b/Source/Scene/Polygon.js @@ -96,7 +96,7 @@ define([ var length = geometries.length; for ( var i = 0; i < length; ++i) { - va.push(context.createVertexArrayFromMesh({ + va.push(context.createVertexArrayFromGeometry({ mesh : geometries[i], attributeIndices : attributeIndices, bufferUsage : bufferUsage, @@ -492,10 +492,10 @@ define([ return result; } - var createMeshFromPositionsPositions = []; - var createMeshFromPositionsBoundingRectangle = new BoundingRectangle(); + var createGeometryFromPositionsPositions = []; + var createGeometryFromPositionsBoundingRectangle = new BoundingRectangle(); - function createMeshFromPositions(polygon, positions, angle, boundingSphere, outerPositions) { + function createGeometryFromPositions(polygon, positions, angle, boundingSphere, outerPositions) { var cleanedPositions = PolygonPipeline.cleanUp(positions); if (cleanedPositions.length < 3) { // Duplicate positions result in not enough positions to form a polygon. @@ -503,7 +503,7 @@ define([ } var tangentPlane = EllipsoidTangentPlane.fromPoints(cleanedPositions, polygon.ellipsoid); - var positions2D = tangentPlane.projectPointsOntoPlane(cleanedPositions, createMeshFromPositionsPositions); + var positions2D = tangentPlane.projectPointsOntoPlane(cleanedPositions, createGeometryFromPositionsPositions); var originalWindingOrder = PolygonPipeline.computeWindingOrder2D(positions2D); if (originalWindingOrder === WindingOrder.CLOCKWISE) { @@ -518,7 +518,7 @@ define([ } var mesh = PolygonPipeline.computeSubdivision(cleanedPositions, indices, polygon._granularity); var boundary = outerPositions || cleanedPositions; - var boundingRectangle = computeBoundingRectangle(tangentPlane, boundary, angle, createMeshFromPositionsBoundingRectangle); + var boundingRectangle = computeBoundingRectangle(tangentPlane, boundary, angle, createGeometryFromPositionsBoundingRectangle); mesh = appendTextureCoordinates(tangentPlane, boundingRectangle, mesh, angle); return new GeometryInstance({ @@ -534,7 +534,7 @@ define([ if (typeof polygon._positions !== 'undefined') { polygon._boundingVolume = BoundingSphere.fromPoints(polygon._positions, polygon._boundingVolume); - mesh = createMeshFromPositions(polygon, polygon._positions, polygon._textureRotationAngle, polygon._boundingVolume); + mesh = createGeometryFromPositions(polygon, polygon._positions, polygon._textureRotationAngle, polygon._boundingVolume); if (typeof mesh !== 'undefined') { geometries.push(mesh); } @@ -545,7 +545,7 @@ define([ // volume doesn't cover the polygon. polygon._boundingVolume = BoundingSphere.fromPoints(outerPositions, polygon._boundingVolume); for (i = 0; i < polygon._polygonHierarchy.length; i++) { - mesh = createMeshFromPositions(polygon, polygon._polygonHierarchy[i], polygon._textureRotationAngle, polygon._boundingVolume, outerPositions); + mesh = createGeometryFromPositions(polygon, polygon._polygonHierarchy[i], polygon._textureRotationAngle, polygon._boundingVolume, outerPositions); if (typeof mesh !== 'undefined') { geometries.push(mesh); } diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index 8ba00501b3e1..edab76fc37e3 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -359,7 +359,7 @@ define([ var va = []; for (i = 0; i < length; ++i) { - va.push(context.createVertexArrayFromMesh({ + va.push(context.createVertexArrayFromGeometry({ mesh : geometries[i], attributeIndices : attributeIndices, bufferUsage : BufferUsage.STATIC_DRAW, diff --git a/Source/Scene/SkyAtmosphere.js b/Source/Scene/SkyAtmosphere.js index 29a47fc63b6d..01b726f79407 100644 --- a/Source/Scene/SkyAtmosphere.js +++ b/Source/Scene/SkyAtmosphere.js @@ -137,7 +137,7 @@ define([ ellipsoid : Ellipsoid.fromCartesian3(this._ellipsoid.getRadii().multiplyByScalar(1.025)), numberOfPartitions : 60 }); - command.vertexArray = context.createVertexArrayFromMesh({ + command.vertexArray = context.createVertexArrayFromGeometry({ mesh : mesh, attributeIndices : GeometryFilters.createAttributeIndices(mesh), bufferUsage : BufferUsage.STATIC_DRAW diff --git a/Source/Scene/SkyBox.js b/Source/Scene/SkyBox.js index 6bd89fe10bb6..1e73e7d13d43 100644 --- a/Source/Scene/SkyBox.js +++ b/Source/Scene/SkyBox.js @@ -158,7 +158,7 @@ define([ command.primitiveType = PrimitiveType.TRIANGLES; command.modelMatrix = Matrix4.IDENTITY.clone(); - command.vertexArray = context.createVertexArrayFromMesh({ + command.vertexArray = context.createVertexArrayFromGeometry({ mesh: mesh, attributeIndices: attributeIndices, bufferUsage: BufferUsage.STATIC_DRAW diff --git a/Source/Scene/SunPostProcess.js b/Source/Scene/SunPostProcess.js index 87361198b993..0883b334a3ff 100644 --- a/Source/Scene/SunPostProcess.js +++ b/Source/Scene/SunPostProcess.js @@ -139,7 +139,7 @@ define([ } }; - vertexArray = context.createVertexArrayFromMesh({ + vertexArray = context.createVertexArrayFromGeometry({ mesh : mesh, attributeIndices : attributeIndices, bufferUsage : BufferUsage.STATIC_DRAW diff --git a/Source/Scene/ViewportQuad.js b/Source/Scene/ViewportQuad.js index 291c8c3fe4fc..30408b7bb34f 100644 --- a/Source/Scene/ViewportQuad.js +++ b/Source/Scene/ViewportQuad.js @@ -144,7 +144,7 @@ define([ } }; - vertexArray = context.createVertexArrayFromMesh({ + vertexArray = context.createVertexArrayFromGeometry({ mesh : mesh, attributeIndices : attributeIndices, bufferUsage : BufferUsage.STATIC_DRAW diff --git a/Specs/Renderer/VertexArrayFactorySpec.js b/Specs/Renderer/VertexArrayFactorySpec.js index d357d0616036..39be0f336297 100644 --- a/Specs/Renderer/VertexArrayFactorySpec.js +++ b/Specs/Renderer/VertexArrayFactorySpec.js @@ -44,13 +44,13 @@ defineSuite([ }); it('creates with no arguments', function() { - va = context.createVertexArrayFromMesh(); + va = context.createVertexArrayFromGeometry(); expect(va.getNumberOfAttributes()).toEqual(0); expect(va.getIndexBuffer()).not.toBeDefined(); }); it('creates with no mesh', function() { - va = context.createVertexArrayFromMesh({ + va = context.createVertexArrayFromGeometry({ vertexLayout : VertexLayout.INTERLEAVED }); expect(va.getNumberOfAttributes()).toEqual(0); @@ -68,7 +68,7 @@ defineSuite([ } }); - var va = context.createVertexArrayFromMesh({ + var va = context.createVertexArrayFromGeometry({ mesh : mesh, attributeIndices : GeometryFilters.createAttributeIndices(mesh) }); @@ -97,7 +97,7 @@ defineSuite([ } }); - var va = context.createVertexArrayFromMesh({ + var va = context.createVertexArrayFromGeometry({ mesh : mesh, attributeIndices : GeometryFilters.createAttributeIndices(mesh), vertexLayout : VertexLayout.INTERLEAVED, @@ -133,7 +133,7 @@ defineSuite([ } }); - var va = context.createVertexArrayFromMesh({ + var va = context.createVertexArrayFromGeometry({ mesh : mesh, attributeIndices : GeometryFilters.createAttributeIndices(mesh) }); @@ -174,7 +174,7 @@ defineSuite([ } }); - var va = context.createVertexArrayFromMesh({ + var va = context.createVertexArrayFromGeometry({ mesh : mesh, attributeIndices : GeometryFilters.createAttributeIndices(mesh), vertexLayout : VertexLayout.INTERLEAVED @@ -218,7 +218,7 @@ defineSuite([ } }); - var va = context.createVertexArrayFromMesh({ + var va = context.createVertexArrayFromGeometry({ mesh : mesh, attributeIndices : GeometryFilters.createAttributeIndices(mesh), vertexLayout : VertexLayout.INTERLEAVED @@ -268,7 +268,7 @@ defineSuite([ }); var attributeIndices = GeometryFilters.createAttributeIndices(mesh); - var va = context.createVertexArrayFromMesh({ + var va = context.createVertexArrayFromGeometry({ mesh : mesh, attributeIndices : attributeIndices, vertexLayout : VertexLayout.INTERLEAVED @@ -328,7 +328,7 @@ defineSuite([ }); var attributeIndices = GeometryFilters.createAttributeIndices(mesh); - var va = context.createVertexArrayFromMesh({ + var va = context.createVertexArrayFromGeometry({ mesh : mesh, attributeIndices : attributeIndices, vertexLayout : VertexLayout.INTERLEAVED @@ -402,7 +402,7 @@ defineSuite([ }); var attributeIndices = GeometryFilters.createAttributeIndices(mesh); - var va = context.createVertexArrayFromMesh({ + var va = context.createVertexArrayFromGeometry({ mesh : mesh, attributeIndices : attributeIndices, vertexLayout : VertexLayout.INTERLEAVED @@ -470,7 +470,7 @@ defineSuite([ }); var attributeIndices = GeometryFilters.createAttributeIndices(mesh); - var va = context.createVertexArrayFromMesh({ + var va = context.createVertexArrayFromGeometry({ mesh : mesh, attributeIndices : attributeIndices, vertexLayout : VertexLayout.INTERLEAVED @@ -549,7 +549,7 @@ defineSuite([ primitiveType : PrimitiveType.POINTS }); - var va = context.createVertexArrayFromMesh({ + var va = context.createVertexArrayFromGeometry({ mesh : mesh }); @@ -577,7 +577,7 @@ defineSuite([ }); expect(function() { - return context.createVertexArrayFromMesh({ + return context.createVertexArrayFromGeometry({ mesh : mesh, vertexLayout : VertexLayout.INTERLEAVED }); @@ -601,7 +601,7 @@ defineSuite([ }); expect(function() { - return context.createVertexArrayFromMesh({ + return context.createVertexArrayFromGeometry({ mesh : mesh, attributeIndices : { position : 0, diff --git a/Specs/Scene/MultifrustumSpec.js b/Specs/Scene/MultifrustumSpec.js index 37672c9a3bec..ee785616b68a 100644 --- a/Specs/Scene/MultifrustumSpec.js +++ b/Specs/Scene/MultifrustumSpec.js @@ -215,7 +215,7 @@ defineSuite([ maximumCorner: maximumCorner }); var attributeIndices = GeometryFilters.createAttributeIndices(mesh); - this._va = context.createVertexArrayFromMesh({ + this._va = context.createVertexArrayFromGeometry({ mesh: mesh, attributeIndices: attributeIndices, bufferUsage: BufferUsage.STATIC_DRAW From 4ad864cf8e720f7ddd63eb2e592344a5b6b4b9b9 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Thu, 6 Jun 2013 09:06:04 -0400 Subject: [PATCH 146/306] Renamed mesh to geometry --- Apps/CesiumViewer/CesiumViewer.js | 26 +- Apps/Sandcastle/gallery/Custom Rendering.html | 20 +- CHANGES.md | 2 +- Source/Core/GeometryFilters.js | 228 ++++++------ Source/Core/PolygonGeometry.js | 26 +- Source/Core/Tipsify.js | 4 +- Source/Renderer/Context.js | 32 +- Source/Scene/CentralBody.js | 36 +- Source/Scene/CentralBodySurface.js | 2 +- Source/Scene/EllipsoidPrimitive.js | 4 +- Source/Scene/ImageryLayer.js | 2 +- Source/Scene/Polygon.js | 54 +-- Source/Scene/Primitive.js | 2 +- Source/Scene/SkyAtmosphere.js | 6 +- Source/Scene/SkyBox.js | 6 +- Source/Scene/SunPostProcess.js | 18 +- Source/Scene/ViewportQuad.js | 18 +- Specs/Core/GeometryFiltersSpec.js | 344 +++++++++--------- Specs/Renderer/VertexArrayFactorySpec.js | 86 ++--- Specs/Scene/MultifrustumSpec.js | 6 +- 20 files changed, 467 insertions(+), 455 deletions(-) diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index 135c00892527..d497e8da0d25 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -92,7 +92,7 @@ define([ var scene = widget.scene; var ellipsoid = widget.centralBody.getEllipsoid(); - var mesh = new GeometryInstance({ + var geometry = new GeometryInstance({ geometry : new ExtentGeometry({ vertexFormat : VertexFormat.POSITION_AND_NORMAL, extent : new Extent( @@ -102,31 +102,31 @@ define([ CesiumMath.toRadians(90.0)), granularity : 0.006 // More than 64K vertices }), - pickData : 'mesh', + pickData : 'geometry', color : Color.CORNFLOWERBLUE }); - var mesh2 = new GeometryInstance({ + var geometry2 = new GeometryInstance({ geometry : new EllipsoidGeometry({ vertexFormat : VertexFormat.POSITION_AND_NORMAL, ellipsoid : new Ellipsoid(500000.0, 500000.0, 1000000.0) }), modelMatrix : Matrix4.multiplyByTranslation(Transforms.eastNorthUpToFixedFrame( ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-95.59777, 40.03883))), new Cartesian3(0.0, 0.0, 500000.0)), - pickData : 'mesh2', + pickData : 'geometry2', color : Color.AQUAMARINE.clone() }); - mesh2.color.alpha = 0.5; - var mesh3 = new GeometryInstance({ + geometry2.color.alpha = 0.5; + var geometry3 = new GeometryInstance({ geometry : new BoxGeometry({ vertexFormat : VertexFormat.POSITION_AND_NORMAL, dimensions : new Cartesian3(1000000.0, 1000000.0, 2000000.0) }), modelMatrix : Matrix4.multiplyByTranslation(Transforms.eastNorthUpToFixedFrame( ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-75.59777, 40.03883))), new Cartesian3(0.0, 0.0, 3000000.0)), - pickData : 'mesh3', + pickData : 'geometry3', color : Color.BLANCHEDALMOND }); - var mesh4 = new GeometryInstance({ + var geometry4 = new GeometryInstance({ geometry : new EllipseGeometry({ vertexFormat : VertexFormat.POSITION_AND_NORMAL, ellipsoid : ellipsoid, @@ -136,11 +136,11 @@ define([ bearing : CesiumMath.PI_OVER_FOUR, height : 1000000.0 }), - pickData : 'mesh4', + pickData : 'geometry4', color : Color.LIME }); var primitive = new Primitive({ - geometryInstances : [mesh, mesh2, mesh3, mesh4], + geometryInstances : [geometry, geometry2, geometry3, geometry4], appearance : new PerGeometryColorClosedTranslucentAppearance() }); scene.getPrimitives().add(primitive); @@ -179,17 +179,17 @@ define([ material : m, renderState : rs }); - var mesh5 = new GeometryInstance({ + var geometry5 = new GeometryInstance({ geometry : new EllipsoidGeometry({ vertexFormat : VertexFormat.ALL, ellipsoid : new Ellipsoid(1000000.0, 500000.0, 500000.0) }), modelMatrix : Matrix4.multiplyByTranslation(Transforms.eastNorthUpToFixedFrame( ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-75.59777, 40.03883))), new Cartesian3(0.0, 0.0, 4500000.0)), - pickData : 'mesh5' + pickData : 'geometry5' }); scene.getPrimitives().add(new Primitive({ - geometryInstances : mesh5, + geometryInstances : geometry5, appearance :appearance, vertexCacheOptimize : false, releasegeometryInstances : true, diff --git a/Apps/Sandcastle/gallery/Custom Rendering.html b/Apps/Sandcastle/gallery/Custom Rendering.html index 3920f7327df1..63b58a3abf0f 100644 --- a/Apps/Sandcastle/gallery/Custom Rendering.html +++ b/Apps/Sandcastle/gallery/Custom Rendering.html @@ -96,14 +96,14 @@ var minimumCorner = maximumCorner.negate(); Cesium.BoundingSphere.fromPoints([minimumCorner, maximumCorner], colorCommand.boundingVolume); - var mesh = Cesium.GeometryFilters.toWireframe(new Cesium.BoxGeometry({ + var geometry = Cesium.GeometryFilters.toWireframe(new Cesium.BoxGeometry({ minimumCorner : minimumCorner, maximumCorner : maximumCorner })); - var attributeIndices = Cesium.GeometryFilters.createAttributeIndices(mesh); + var attributeIndices = Cesium.GeometryFilters.createAttributeIndices(geometry); colorCommand.vertexArray = pickCommand.vertexArray = context.createVertexArrayFromGeometry({ - mesh : mesh, + geometry : geometry, attributeIndices : attributeIndices, bufferUsage : Cesium.BufferUsage.STATIC_DRAW }); @@ -204,15 +204,15 @@ var maximumCorner = dimensions.multiplyByScalar(0.5); var minimumCorner = maximumCorner.negate(); - var mesh = Cesium.GeometryFilters.toWireframe(new Cesium.BoxGeometry({ + var geometry = Cesium.GeometryFilters.toWireframe(new Cesium.BoxGeometry({ minimumCorner : minimumCorner, maximumCorner : maximumCorner })); - mesh.attributes.position3D = mesh.attributes.position; - delete mesh.attributes.position; + geometry.attributes.position3D = geometry.attributes.position; + delete geometry.attributes.position; if (mode === Cesium.SceneMode.SCENE3D) { - mesh.attributes.position2D = { // Not actually used in shader + geometry.attributes.position2D = { // Not actually used in shader value : [0.0, 0.0] }; @@ -222,7 +222,7 @@ ], colorCommand.boundingVolume); } else { - var positions = mesh.attributes.position3D.values; + var positions = geometry.attributes.position3D.values; var projectedPositions = []; var projectedPositionsFlat = []; for ( var i = 0; i < positions.length; i += 3) { @@ -253,7 +253,7 @@ bv3D.union(bv2D, colorCommand.boundingVolume); } - mesh.attributes.position2D = { + geometry.attributes.position2D = { componentDatatype : Cesium.ComponentDatatype.FLOAT, componentsPerAttribute : 3, values : projectedPositionsFlat @@ -262,7 +262,7 @@ colorCommand.vertexArray = colorCommand.vertexArray && colorCommand.vertexArray.destroy(); colorCommand.vertexArray = pickCommand.vertexArray = context.createVertexArrayFromGeometry({ - mesh : mesh, + geometry : geometry, attributeIndices : this._attributeIndices, bufferUsage : Cesium.BufferUsage.STATIC_DRAW }); diff --git a/CHANGES.md b/CHANGES.md index d0d076e66e4a..ce5995ea83f4 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -19,7 +19,7 @@ Beta Releases * Removed `PlaneTessellator`. It was incomplete and not used. * Renamed `MeshFilters` to `GeometryFilters`. * Renamed `MeshFilters.toWireframeInPlace` to `GeometryFilters.toWireframe`. - * Renamed `Context.createVertexArrayFromMesh` to `Context.createVertexArrayFromGeometry`. + * Renamed `Context.createVertexArrayFromMesh` to `Context.createVertexArrayFromGeometry`. Likewise, renamed `mesh` constructor property to `geometry`. * Renamed `ComponentDatatype.*.toTypedArray` to `ComponentDatatype.*.createTypedArray`. * Replaced `Uniform.getFrameNumber` and `Uniform.getTime` with `Uniform.getFrameState`, which returns the full frame state. * Removed `Polygon.configureExtent`. diff --git a/Source/Core/GeometryFilters.js b/Source/Core/GeometryFilters.js index ae6a01e224a5..5389f9fbb4dd 100644 --- a/Source/Core/GeometryFilters.js +++ b/Source/Core/GeometryFilters.js @@ -41,23 +41,23 @@ define([ var GeometryFilters = {}; /** - * Converts a mesh's triangle indices to line indices. The mesh's indexList with + * Converts a geometry's triangle indices to line indices. The geometry's indexList with * a primitive type of triangles, triangleStrip, or trangleFan is converted to a * list of indices with a primitive type of lines. *

    - * The mesh argument should use the standard layout like the mesh returned by {@link BoxGeometry}. + * The geometry argument should use the standard layout like the geometry returned by {@link BoxGeometry}. *

    - * This filter is commonly used to create a wireframe mesh for visual debugging. + * This filter is commonly used to create a wireframe geometry for visual debugging. * - * @param {Geometry} mesh The mesh to filter, which is modified in place. + * @param {Geometry} geometry The geometry to filter, which is modified in place. * - * @returns The modified mesh argument, with its triangle indices converted to lines. + * @returns The modified geometry argument, with its triangle indices converted to lines. * * @example - * var mesh = new BoxGeometry(); - * mesh = GeometryFilters.toWireframe(mesh); + * var geometry = new BoxGeometry(); + * geometry = GeometryFilters.toWireframe(geometry); */ - GeometryFilters.toWireframe = function(mesh) { + GeometryFilters.toWireframe = function(geometry) { function addTriangle(lines, i0, i1, i2) { lines.push(i0); lines.push(i1); @@ -108,36 +108,36 @@ define([ return lines; } - if (typeof mesh !== 'undefined') { - var indices = mesh.indexList; + if (typeof geometry !== 'undefined') { + var indices = geometry.indexList; if (typeof indices !== 'undefined') { - switch (mesh.primitiveType) { + switch (geometry.primitiveType) { case PrimitiveType.TRIANGLES: - mesh.indexList = trianglesToLines(indices); + geometry.indexList = trianglesToLines(indices); break; case PrimitiveType.TRIANGLE_STRIP: - mesh.indexList = triangleStripToLines(indices); + geometry.indexList = triangleStripToLines(indices); break; case PrimitiveType.TRIANGLE_FAN: - mesh.indexList = triangleFanToLines(indices); + geometry.indexList = triangleFanToLines(indices); break; } - mesh.primitiveType = PrimitiveType.LINES; + geometry.primitiveType = PrimitiveType.LINES; } } - return mesh; + return geometry; }; /** * DOC_TBA */ - GeometryFilters.createAttributeIndices = function(mesh) { + GeometryFilters.createAttributeIndices = function(geometry) { var indices = {}; - if (typeof mesh !== 'undefined') { - var attributes = mesh.attributes; + if (typeof geometry !== 'undefined') { + var attributes = geometry.attributes; var j = 0; for ( var name in attributes) { @@ -168,27 +168,27 @@ define([ }; /** - * Reorders a mesh's indices to achieve better performance from the GPU's pre-vertex-shader cache. - * Each list of indices in the mesh's indexList is reordered to keep the same index-vertex correspondence. + * Reorders a geometry's indices to achieve better performance from the GPU's pre-vertex-shader cache. + * Each list of indices in the geometry's indexList is reordered to keep the same index-vertex correspondence. *

    - * The mesh argument should use the standard layout like the mesh returned by {@link BoxGeometry}. + * The geometry argument should use the standard layout like the geometry returned by {@link BoxGeometry}. *

    - * @param {Geometry} mesh The mesh to filter, which is modified in place. + * @param {Geometry} geometry The geometry to filter, which is modified in place. * - * @exception {DeveloperError} All mesh attribute lists must have the same number of attributes. + * @exception {DeveloperError} All geometry attribute lists must have the same number of attributes. * - * @returns The modified mesh argument, with its vertices and indices reordered for the GPU's pre-vertex-shader cache. + * @returns The modified geometry argument, with its vertices and indices reordered for the GPU's pre-vertex-shader cache. * * @see GeometryFilters.reorderForPostVertexCache * * @example - * var mesh = new EllipsoidGeometry(...); - * mesh = GeometryFilters.reorderForPreVertexCache(mesh); + * var geometry = new EllipsoidGeometry(...); + * geometry = GeometryFilters.reorderForPreVertexCache(geometry); */ - GeometryFilters.reorderForPreVertexCache = function(mesh) { - if (typeof mesh !== 'undefined') { - var numVertices = Geometry.computeNumberOfVertices(mesh); + GeometryFilters.reorderForPreVertexCache = function(geometry) { + if (typeof geometry !== 'undefined') { + var numVertices = Geometry.computeNumberOfVertices(geometry); var indexCrossReferenceOldToNew = []; for ( var i = 0; i < numVertices; i++) { @@ -196,7 +196,7 @@ define([ } //Construct cross reference and reorder indices - var indexList = mesh.indexList; + var indexList = geometry.indexList; if (typeof indexList !== 'undefined') { var indicesIn = indexList; var numIndices = indicesIn.length; @@ -222,11 +222,11 @@ define([ ++intoIndicesIn; ++intoIndicesOut; } - mesh.indexList = indicesOut; + geometry.indexList = indicesOut; } //Reorder Vertices - var attributes = mesh.attributes; + var attributes = geometry.attributes; for ( var property in attributes) { if (attributes.hasOwnProperty(property) && attributes[property].values) { var elementsIn = attributes[property].values; @@ -244,17 +244,17 @@ define([ } } } - return mesh; + return geometry; }; /** - * Reorders a mesh's indices to achieve better performance from the GPU's post vertex-shader cache by using the Tipsify algorithm. - * Each list of indices in the mesh's indexList is optimally reordered. + * Reorders a geometry's indices to achieve better performance from the GPU's post vertex-shader cache by using the Tipsify algorithm. + * Each list of indices in the geometry's indexList is optimally reordered. *

    - * The mesh argument should use the standard layout like the mesh returned by {@link BoxGeometry}. + * The geometry argument should use the standard layout like the geometry returned by {@link BoxGeometry}. *

    - * @param {Geometry} mesh The mesh to filter, which is modified in place. + * @param {Geometry} geometry The geometry to filter, which is modified in place. * @param {Number} [cacheCapacity=24] The number of vertices that can be held in the GPU's vertex cache. * * @exception {DeveloperError} Geometry's index list must be defined. @@ -262,7 +262,7 @@ define([ * @exception {DeveloperError} Geometry's index list's maximum index value must be greater than zero. * @exception {DeveloperError} cacheCapacity must be greater than two. * - * @returns The modified mesh argument, with its indices optimally reordered for the post-vertex-shader cache. + * @returns The modified geometry argument, with its indices optimally reordered for the post-vertex-shader cache. * * @see GeometryFilters.reorderForPreVertexCache * @see Tipsify @@ -271,12 +271,12 @@ define([ * by Sander, Nehab, and Barczak * * @example - * var mesh = new EllipsoidGeometry(...); - * mesh = GeometryFilters.reorderForPostVertexCache(mesh); + * var geometry = new EllipsoidGeometry(...); + * geometry = GeometryFilters.reorderForPostVertexCache(geometry); */ - GeometryFilters.reorderForPostVertexCache = function(mesh, cacheCapacity) { - if (typeof mesh !== 'undefined') { - var indices = mesh.indexList; + GeometryFilters.reorderForPostVertexCache = function(geometry, cacheCapacity) { + if (typeof geometry !== 'undefined') { + var indices = geometry.indexList; if (typeof indices !== 'undefined') { var numIndices = indices.length; var maximumIndex = 0; @@ -285,14 +285,14 @@ define([ maximumIndex = indices[j]; } } - mesh.indexList = Tipsify.tipsify({ + geometry.indexList = Tipsify.tipsify({ indices : indices, maximumIndex : maximumIndex, cacheSize : cacheCapacity }); } } - return mesh; + return geometry; }; GeometryFilters._copyAttributesDescriptions = function(attributes) { @@ -326,31 +326,31 @@ define([ } /** - * DOC_TBA. Old mesh is not guaranteed to be copied. + * DOC_TBA. Old geometry is not guaranteed to be copied. * - * @exception {DeveloperError} mesh.primitiveType must equal to PrimitiveType.TRIANGLES. - * @exception {DeveloperError} All mesh attribute lists must have the same number of attributes. + * @exception {DeveloperError} geometry.primitiveType must equal to PrimitiveType.TRIANGLES. + * @exception {DeveloperError} All geometry attribute lists must have the same number of attributes. */ - GeometryFilters.fitToUnsignedShortIndices = function(mesh) { + GeometryFilters.fitToUnsignedShortIndices = function(geometry) { var geometries = []; - if (typeof mesh !== 'undefined') { - if (mesh.primitiveType !== PrimitiveType.TRIANGLES) { - throw new DeveloperError('mesh.primitiveType must equal to PrimitiveType.TRIANGLES.'); + if (typeof geometry !== 'undefined') { + if (geometry.primitiveType !== PrimitiveType.TRIANGLES) { + throw new DeveloperError('geometry.primitiveType must equal to PrimitiveType.TRIANGLES.'); } - var numberOfVertices = Geometry.computeNumberOfVertices(mesh); + var numberOfVertices = Geometry.computeNumberOfVertices(geometry); // If there's an index list and more than 64K attributes, it is possible that // some indices are outside the range of unsigned short [0, 64K - 1] var sixtyFourK = 64 * 1024; - if (typeof mesh.indexList !== 'undefined' && (numberOfVertices > sixtyFourK)) { + if (typeof geometry.indexList !== 'undefined' && (numberOfVertices > sixtyFourK)) { var oldToNewIndex = []; var newIndices = []; var currentIndex = 0; - var newAttributes = GeometryFilters._copyAttributesDescriptions(mesh.attributes); + var newAttributes = GeometryFilters._copyAttributesDescriptions(geometry.attributes); - var originalIndices = mesh.indexList; + var originalIndices = geometry.indexList; var numberOfIndices = originalIndices.length; for ( var j = 0; j < numberOfIndices; j += 3) { @@ -365,7 +365,7 @@ define([ i0 = currentIndex++; oldToNewIndex[x0] = i0; - copyVertex(newAttributes, mesh.attributes, x0); + copyVertex(newAttributes, geometry.attributes, x0); } var i1 = oldToNewIndex[x1]; @@ -373,7 +373,7 @@ define([ i1 = currentIndex++; oldToNewIndex[x1] = i1; - copyVertex(newAttributes, mesh.attributes, x1); + copyVertex(newAttributes, geometry.attributes, x1); } var i2 = oldToNewIndex[x2]; @@ -381,7 +381,7 @@ define([ i2 = currentIndex++; oldToNewIndex[x2] = i2; - copyVertex(newAttributes, mesh.attributes, x2); + copyVertex(newAttributes, geometry.attributes, x2); } newIndices.push(i0); @@ -393,14 +393,14 @@ define([ geometries.push(new Geometry({ attributes : newAttributes, indexList : newIndices, - primitiveType : mesh.primitiveType + primitiveType : geometry.primitiveType })); // Reset for next vertex-array oldToNewIndex = []; newIndices = []; currentIndex = 0; - newAttributes = GeometryFilters._copyAttributesDescriptions(mesh.attributes); + newAttributes = GeometryFilters._copyAttributesDescriptions(geometry.attributes); } } @@ -409,12 +409,12 @@ define([ geometries.push(new Geometry({ attributes : newAttributes, indexList : newIndices, - primitiveType : mesh.primitiveType + primitiveType : geometry.primitiveType })); } } else { // No need to split into multiple geometries - geometries.push(mesh); + geometries.push(geometry); } } @@ -424,13 +424,13 @@ define([ /** * DOC_TBA */ - GeometryFilters.projectTo2D = function(mesh, projection) { - if (typeof mesh !== 'undefined' && typeof mesh.attributes.position !== 'undefined') { + GeometryFilters.projectTo2D = function(geometry, projection) { + if (typeof geometry !== 'undefined' && typeof geometry.attributes.position !== 'undefined') { projection = typeof projection !== 'undefined' ? projection : new GeographicProjection(); var ellipsoid = projection.getEllipsoid(); // Project original positions to 2D. - var wgs84Positions = mesh.attributes.position.values; + var wgs84Positions = geometry.attributes.position.values; var projectedPositions = []; for ( var i = 0; i < wgs84Positions.length; i += 3) { @@ -440,18 +440,18 @@ define([ } // Rename original positions to WGS84 Positions. - mesh.attributes.position3D = mesh.attributes.position; + geometry.attributes.position3D = geometry.attributes.position; // Replace original positions with 2D projected positions - mesh.attributes.position2D = { + geometry.attributes.position2D = { componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 2, values : projectedPositions }; - delete mesh.attributes.position; + delete geometry.attributes.position; } - return mesh; + return geometry; }; var encodedResult = { @@ -460,41 +460,41 @@ define([ }; /** - * Encodes floating-point mesh attribute values as two separate attributes to improve + * Encodes floating-point geometry attribute values as two separate attributes to improve * rendering precision using the same encoding as {@link EncodedCartesian3}. *

    * This is commonly used to create high-precision position vertex attributes. *

    * - * @param {Geometry} mesh The mesh to filter, which is modified in place. + * @param {Geometry} geometry The geometry to filter, which is modified in place. * @param {String} [attributeName='position'] The name of the attribute. * @param {String} [attributeHighName='positionHigh'] The name of the attribute for the encoded high bits. * @param {String} [attributeLowName='positionLow'] The name of the attribute for the encoded low bits. * - * @returns The modified mesh argument, with its encoded attribute. + * @returns The modified geometry argument, with its encoded attribute. * - * @exception {DeveloperError} mesh is required. - * @exception {DeveloperError} mesh must have attribute matching the attributeName argument. + * @exception {DeveloperError} geometry is required. + * @exception {DeveloperError} geometry must have attribute matching the attributeName argument. * @exception {DeveloperError} The attribute componentDatatype must be ComponentDatatype.FLOAT. * * @example - * mesh = GeometryFilters.encodeAttribute(mesh, 'position3D', 'position3DHigh', 'position3DLow'); + * geometry = GeometryFilters.encodeAttribute(geometry, 'position3D', 'position3DHigh', 'position3DLow'); * * @see EncodedCartesian3 */ - GeometryFilters.encodeAttribute = function(mesh, attributeName, attributeHighName, attributeLowName) { + GeometryFilters.encodeAttribute = function(geometry, attributeName, attributeHighName, attributeLowName) { attributeName = defaultValue(attributeName, 'position'); attributeHighName = defaultValue(attributeHighName, 'positionHigh'); attributeLowName = defaultValue(attributeLowName, 'positionLow'); - if (typeof mesh === 'undefined') { - throw new DeveloperError('mesh is required.'); + if (typeof geometry === 'undefined') { + throw new DeveloperError('geometry is required.'); } - var attribute = mesh.attributes[attributeName]; + var attribute = geometry.attributes[attributeName]; if (typeof attribute === 'undefined') { - throw new DeveloperError('mesh must have attribute matching the attributeName argument: ' + attributeName + '.'); + throw new DeveloperError('geometry must have attribute matching the attributeName argument: ' + attributeName + '.'); } if (attribute.componentDatatype !== ComponentDatatype.FLOAT) { @@ -512,19 +512,19 @@ define([ lowValues[i] = encodedResult.low; } - mesh.attributes[attributeHighName] = new GeometryAttribute({ + geometry.attributes[attributeHighName] = new GeometryAttribute({ componentDatatype : attribute.componentDatatype, componentsPerAttribute : attribute.componentsPerAttribute, values : highValues }); - mesh.attributes[attributeLowName] = new GeometryAttribute({ + geometry.attributes[attributeLowName] = new GeometryAttribute({ componentDatatype : attribute.componentDatatype, componentsPerAttribute : attribute.componentsPerAttribute, values : lowValues }); - delete mesh.attributes[attributeName]; + delete geometry.attributes[attributeName]; - return mesh; + return geometry; }; var scratch = new Cartesian3(); @@ -560,7 +560,7 @@ define([ /** * DOC_TBA * - * @exception {DeveloperError} mesh is required. + * @exception {DeveloperError} instance is required. */ GeometryFilters.transformToWorldCoordinates = function(instance) { if (typeof instance === 'undefined') { @@ -687,9 +687,9 @@ define([ var sourceValuesLength; // PERFORMANCE_IDEA: Interleave here instead of createVertexArrayFromGeometry to save a copy. - // This will require adding offset and stride to the mesh. + // This will require adding offset and stride to the geometry. - // Combine attributes from each mesh into a single typed array + // Combine attributes from each geometry into a single typed array for (name in attributes) { if (attributes.hasOwnProperty(name)) { values = attributes[name].values; @@ -776,7 +776,7 @@ define([ for (i = 0; i < length; ++i) { var bs = instances[i].geometry.boundingSphere; if (typeof bs === 'undefined') { - // If any geometries have an undefined bounding sphere, then so does the combined mesh + // If any geometries have an undefined bounding sphere, then so does the combined geometry boundingSphere = undefined; break; } @@ -803,44 +803,44 @@ define([ var v2 = new Cartesian3(); /** - * Computes the normals of all vertices in a mesh based on the normals of triangles that include the vertex. + * Computes the normals of all vertices in a geometry based on the normals of triangles that include the vertex. * This assumes a counter-clockwise vertex winding order. * - * @param {Geometry} mesh The mesh to filter, which is modified in place. - * @param {Object} mesh.attributes.position + * @param {Geometry} geometry The geometry to filter, which is modified in place. + * @param {Object} geometry.attributes.position * - * @returns The modified mesh argument. + * @returns The modified geometry argument. * - * @exception {DeveloperError} mesh.attributes.position.values is required - * @exception {DeveloperError} mesh.attributes.position.values.length must be a multiple of 3 + * @exception {DeveloperError} geometry.attributes.position.values is required + * @exception {DeveloperError} geometry.attributes.position.values.length must be a multiple of 3 * * @example - * mesh = GeometryFilters.computeNormal(mesh); + * geometry = GeometryFilters.computeNormal(geometry); * */ - GeometryFilters.computeNormal = function(mesh) { - if (typeof mesh === 'undefined') { - throw new DeveloperError('mesh is required.'); + GeometryFilters.computeNormal = function(geometry) { + if (typeof geometry === 'undefined') { + throw new DeveloperError('geometry is required.'); } - var attributes = mesh.attributes; + var attributes = geometry.attributes; if (typeof attributes.position === 'undefined' || typeof attributes.position.values === 'undefined') { - throw new DeveloperError('mesh.attributes.position.values is required'); + throw new DeveloperError('geometry.attributes.position.values is required'); } - var vertices = mesh.attributes.position.values; - if (mesh.attributes.position.componentsPerAttribute !== 3 || vertices.length % 3 !== 0) { - throw new DeveloperError('mesh.attributes.position.values.length must be a multiple of 3'); + var vertices = geometry.attributes.position.values; + if (geometry.attributes.position.componentsPerAttribute !== 3 || vertices.length % 3 !== 0) { + throw new DeveloperError('geometry.attributes.position.values.length must be a multiple of 3'); } - var indices = mesh.indexList; + var indices = geometry.indexList; if (typeof indices === 'undefined') { - return mesh; + return geometry; } - if (mesh.primitiveType !== PrimitiveType.TRIANGLES || typeof indices === 'undefined' || + if (geometry.primitiveType !== PrimitiveType.TRIANGLES || typeof indices === 'undefined' || indices.length < 2 || indices.length % 3 !== 0) { - return mesh; + return geometry; } - var numVertices = mesh.attributes.position.values.length / 3; + var numVertices = geometry.attributes.position.values.length / 3; var numIndices = indices.length; var normalsPerVertex = new Array(numVertices); var normalsPerTriangle = new Array(numIndices / 3); @@ -910,14 +910,14 @@ define([ j++; } - if (typeof mesh.attributes.normal === 'undefined') { - mesh.attributes.normal = new GeometryAttribute({ + if (typeof geometry.attributes.normal === 'undefined') { + geometry.attributes.normal = new GeometryAttribute({ componentDatatype: ComponentDatatype.FLOAT, componentsPerAttribute: 3, values: new Array(numVertices * 3) }); } - var normalValues = mesh.attributes.normal.values; + var normalValues = geometry.attributes.normal.values; for (i = 0; i < numVertices; i++) { var i3 = i * 3; vertexNormalData = normalsPerVertex[i]; @@ -937,7 +937,7 @@ define([ } } - return mesh; + return geometry; }; var normalScratch = new Cartesian3(); diff --git a/Source/Core/PolygonGeometry.js b/Source/Core/PolygonGeometry.js index 72eb36d3cc5f..459de8fa5a5b 100644 --- a/Source/Core/PolygonGeometry.js +++ b/Source/Core/PolygonGeometry.js @@ -208,7 +208,7 @@ define([ var polygonHierarchy = options.polygonHierarchy; var geometries = []; - var mesh; + var geometry; var boundingSphere; var i; @@ -219,9 +219,9 @@ define([ outerPositions = positions; boundingSphere = BoundingSphere.fromPoints(positions); - mesh = createGeometryFromPositions(ellipsoid, positions, boundingSphere, granularity); - if (typeof mesh !== 'undefined') { - geometries.push(mesh); + geometry = createGeometryFromPositions(ellipsoid, positions, boundingSphere, granularity); + if (typeof geometry !== 'undefined') { + geometries.push(geometry); } } else if (typeof polygonHierarchy !== 'undefined') { // create from a polygon hierarchy @@ -272,22 +272,22 @@ define([ boundingSphere = BoundingSphere.fromPoints(outerPositions); for (i = 0; i < polygonHierarchy.length; i++) { - mesh = createGeometryFromPositions(ellipsoid, polygonHierarchy[i], boundingSphere, granularity); - if (typeof mesh !== 'undefined') { - geometries.push(mesh); + geometry = createGeometryFromPositions(ellipsoid, polygonHierarchy[i], boundingSphere, granularity); + if (typeof geometry !== 'undefined') { + geometries.push(geometry); } } } else { throw new DeveloperError('positions or hierarchy must be supplied.'); } - mesh = GeometryFilters.combine(geometries); - mesh = PolygonPipeline.scaleToGeodeticHeight(mesh, height, ellipsoid); + geometry = GeometryFilters.combine(geometries); + geometry = PolygonPipeline.scaleToGeodeticHeight(geometry, height, ellipsoid); var attributes = {}; if (vertexFormat.position) { - attributes.position = mesh.attributes.position; + attributes.position = geometry.attributes.position; } if (vertexFormat.st || vertexFormat.normal || vertexFormat.tangent || vertexFormat.binormal) { @@ -301,7 +301,7 @@ define([ origin.x = boundingRectangle.x; origin.y = boundingRectangle.y; - var flatPositions = mesh.attributes.position.values; + var flatPositions = geometry.attributes.position.values; var length = flatPositions.length; var textureCoordinates = vertexFormat.st ? new Array(2 * (length / 3)) : undefined; @@ -419,12 +419,12 @@ define([ * * @type Array */ - this.indexList = mesh.indexList; + this.indexList = geometry.indexList; /** * DOC_TBA */ - this.primitiveType = mesh.primitiveType; + this.primitiveType = geometry.primitiveType; /** * A tight-fitting bounding sphere that encloses the vertices of the geometry. diff --git a/Source/Core/Tipsify.js b/Source/Core/Tipsify.js index c62884a5dc00..2adde8cd21aa 100644 --- a/Source/Core/Tipsify.js +++ b/Source/Core/Tipsify.js @@ -25,7 +25,7 @@ define([ * Calculates the average cache miss ratio (ACMR) for a given set of indices. * * @param {Array} description.indices Lists triads of numbers corresponding to the indices of the vertices - * in the vertex buffer that define the mesh's triangles. + * in the vertex buffer that define the geometry's triangles. * @param {Number} [description.maximumIndex] The maximum value of the elements in args.indices. * If not supplied, this value will be computed. * @param {Number} [description.cacheSize=24] The number of vertices that can be stored in the cache at any one time. @@ -100,7 +100,7 @@ define([ * Optimizes triangles for the post-vertex shader cache. * * @param {Array} description.indices Lists triads of numbers corresponding to the indices of the vertices - * in the vertex buffer that define the mesh's triangles. + * in the vertex buffer that define the geometry's triangles. * @param {Number} [description.maximumIndex] The maximum value of the elements in args.indices. * If not supplied, this value will be computed. * @param {Number} [description.cacheSize=24] The number of vertices that can be stored in the cache at any one time. diff --git a/Source/Renderer/Context.js b/Source/Renderer/Context.js index 03d6711c7c3b..011a2fcfa749 100644 --- a/Source/Renderer/Context.js +++ b/Source/Renderer/Context.js @@ -2286,28 +2286,28 @@ define([ } /** - * Creates a vertex array from a mesh. A mesh contains vertex attributes and optional index data + * Creates a vertex array from a geometry. A geometry contains vertex attributes and optional index data * in system memory, whereas a vertex array contains vertex buffers and an optional index buffer in WebGL * memory for use with rendering. *

    - * The mesh argument should use the standard layout like the mesh returned by {@link BoxGeometry}. + * The geometry argument should use the standard layout like the geometry returned by {@link BoxGeometry}. *

    * creationArguments can have four properties: *
      - *
    • mesh: The source mesh containing data used to create the vertex array.
    • - *
    • attributeIndices: An object that maps mesh attribute names to vertex shader attribute indices.
    • + *
    • geometry: The source geometry containing data used to create the vertex array.
    • + *
    • attributeIndices: An object that maps geometry attribute names to vertex shader attribute indices.
    • *
    • bufferUsage: The expected usage pattern of the vertex array's buffers. On some WebGL implementations, this can significantly affect performance. See {@link BufferUsage}. Default: BufferUsage.DYNAMIC_DRAW.
    • *
    • vertexLayout: Determines if all attributes are interleaved in a single vertex buffer or if each attribute is stored in a separate vertex buffer. Default: VertexLayout.SEPARATE.
    • *
    *
    - * If creationArguments is not specified or the mesh contains no data, the returned vertex array is empty. + * If creationArguments is not specified or the geometry contains no data, the returned vertex array is empty. * * @memberof Context * - * @param {Object} [creationArguments=undefined] An object defining the mesh, attribute indices, buffer usage, and vertex layout used to create the vertex array. + * @param {Object} [creationArguments=undefined] An object defining the geometry, attribute indices, buffer usage, and vertex layout used to create the vertex array. * * @exception {RuntimeError} Each attribute list must have the same number of vertices. - * @exception {DeveloperError} The mesh must have zero or one index lists. + * @exception {DeveloperError} The geometry must have zero or one index lists. * @exception {DeveloperError} Index n is used by more than one attribute. * * @see Context#createVertexArray @@ -2320,10 +2320,10 @@ define([ * // Example 1. Creates a vertex array for rendering a box. The default dynamic draw * // usage is used for the created vertex and index buffer. The attributes are not * // interleaved by default. - * var mesh = new BoxGeometry(); + * var geometry = new BoxGeometry(); * var va = context.createVertexArrayFromGeometry({ - * mesh : mesh, - * attributeIndices : GeometryFilters.createAttributeIndices(mesh), + * geometry : geometry, + * attributeIndices : GeometryFilters.createAttributeIndices(geometry), * }); * * //////////////////////////////////////////////////////////////////////////////// @@ -2331,8 +2331,8 @@ define([ * // Example 2. Creates a vertex array with interleaved attributes in a * // single vertex buffer. The vertex and index buffer have static draw usage. * var va = context.createVertexArrayFromGeometry({ - * mesh : mesh, - * attributeIndices : GeometryFilters.createAttributeIndices(mesh), + * geometry : geometry, + * attributeIndices : GeometryFilters.createAttributeIndices(geometry), * bufferUsage : BufferUsage.STATIC_DRAW, * vertexLayout : VertexLayout.INTERLEAVED * }); @@ -2345,7 +2345,7 @@ define([ */ Context.prototype.createVertexArrayFromGeometry = function(creationArguments) { var ca = defaultValue(creationArguments, defaultValue.EMPTY_OBJECT); - var mesh = defaultValue(ca.mesh, defaultValue.EMPTY_OBJECT); + var geometry = defaultValue(ca.geometry, defaultValue.EMPTY_OBJECT); var bufferUsage = defaultValue(ca.bufferUsage, BufferUsage.DYNAMIC_DRAW); @@ -2355,7 +2355,7 @@ define([ var name; var attribute; var vaAttributes = []; - var attributes = mesh.attributes; + var attributes = geometry.attributes; if (interleave) { // Use a single vertex buffer with interleaved vertices. @@ -2410,9 +2410,9 @@ define([ } var indexBuffer; - var indexList = mesh.indexList; + var indexList = geometry.indexList; if (typeof indexList !== 'undefined') { - if ((Geometry.computeNumberOfVertices(mesh) > 64 * 1024) && this.getElementIndexUint()) { + if ((Geometry.computeNumberOfVertices(geometry) > 64 * 1024) && this.getElementIndexUint()) { indexBuffer = this.createIndexBuffer(new Uint32Array(indexList), bufferUsage, IndexDatatype.UNSIGNED_INT); } else{ indexBuffer = this.createIndexBuffer(new Uint16Array(indexList), bufferUsage, IndexDatatype.UNSIGNED_SHORT); diff --git a/Source/Scene/CentralBody.js b/Source/Scene/CentralBody.js index a4142acf1226..f4f27e77aa3c 100644 --- a/Source/Scene/CentralBody.js +++ b/Source/Scene/CentralBody.js @@ -14,6 +14,8 @@ define([ '../Core/Ellipsoid', '../Core/Extent', '../Core/GeographicProjection', + '../Core/Geometry', + '../Core/GeometryAttribute', '../Core/Intersect', '../Core/Math', '../Core/Matrix4', @@ -55,6 +57,8 @@ define([ Ellipsoid, Extent, GeographicProjection, + Geometry, + GeometryAttribute, Intersect, CesiumMath, Matrix4, @@ -331,7 +335,7 @@ define([ var occludeePoint; var occluded; var datatype; - var mesh; + var geometry; var rect; var positions; var occluder = centralBody._occluder; @@ -361,17 +365,17 @@ define([ if (typeof centralBody._northPoleCommand.vertexArray === 'undefined') { centralBody._northPoleCommand.boundingVolume = BoundingSphere.fromExtent3D(extent, centralBody._ellipsoid); - mesh = { + geometry = new Geometry({ attributes : { - position : { + position : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 2, values : positions - } + }) } - }; + }); centralBody._northPoleCommand.vertexArray = context.createVertexArrayFromGeometry({ - mesh : mesh, + geometry : geometry, attributeIndices : { position : 0 }, @@ -409,17 +413,17 @@ define([ if (typeof centralBody._southPoleCommand.vertexArray === 'undefined') { centralBody._southPoleCommand.boundingVolume = BoundingSphere.fromExtent3D(extent, centralBody._ellipsoid); - mesh = { + geometry = new Geometry({ attributes : { - position : { + position : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 2, values : positions - } + }) } - }; + }); centralBody._southPoleCommand.vertexArray = context.createVertexArrayFromGeometry({ - mesh : mesh, + geometry : geometry, attributeIndices : { position : 0 }, @@ -541,19 +545,19 @@ define([ // depth plane if (!this._depthCommand.vertexArray) { - var mesh = { + var geometry = new Geometry({ attributes : { - position : { + position : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 3, values : depthQuad - } + }) }, indexList : [0, 1, 2, 2, 1, 3], primitiveType : PrimitiveType.TRIANGLES - }; + }); this._depthCommand.vertexArray = context.createVertexArrayFromGeometry({ - mesh : mesh, + geometry : geometry, attributeIndices : { position : 0 }, diff --git a/Source/Scene/CentralBodySurface.js b/Source/Scene/CentralBodySurface.js index 6c1b200c40ac..21cdcb617a5d 100644 --- a/Source/Scene/CentralBodySurface.js +++ b/Source/Scene/CentralBodySurface.js @@ -702,7 +702,7 @@ define([ }); GeometryFilters.toWireframe(sphere); surface._debug.boundingSphereVA = context.createVertexArrayFromGeometry({ - mesh : sphere, + geometry : sphere, attributeIndices : GeometryFilters.createAttributeIndices(sphere) }); } diff --git a/Source/Scene/EllipsoidPrimitive.js b/Source/Scene/EllipsoidPrimitive.js index 9b8b23211276..70c3b318dc6f 100644 --- a/Source/Scene/EllipsoidPrimitive.js +++ b/Source/Scene/EllipsoidPrimitive.js @@ -196,12 +196,12 @@ define([ return vertexArray; } - var mesh = new BoxGeometry({ + var geometry = new BoxGeometry({ dimensions : new Cartesian3(2.0, 2.0, 2.0) }); vertexArray = context.createVertexArrayFromGeometry({ - mesh: mesh, + geometry: geometry, attributeIndices: attributeIndices, bufferUsage: BufferUsage.STATIC_DRAW }); diff --git a/Source/Scene/ImageryLayer.js b/Source/Scene/ImageryLayer.js index 4f3f1720b357..e074abf36ea2 100644 --- a/Source/Scene/ImageryLayer.js +++ b/Source/Scene/ImageryLayer.js @@ -816,7 +816,7 @@ define([ }; reproject.vertexArray = context.createVertexArrayFromGeometry({ - mesh : reprojectGeometry, + geometry : reprojectGeometry, attributeIndices : reprojectAttribInds, bufferUsage : BufferUsage.STATIC_DRAW }); diff --git a/Source/Scene/Polygon.js b/Source/Scene/Polygon.js index 0e20c265f555..a14ad5d1fbd5 100644 --- a/Source/Scene/Polygon.js +++ b/Source/Scene/Polygon.js @@ -97,7 +97,7 @@ define([ var length = geometries.length; for ( var i = 0; i < length; ++i) { va.push(context.createVertexArrayFromGeometry({ - mesh : geometries[i], + geometry : geometries[i], attributeIndices : attributeIndices, bufferUsage : bufferUsage, vertexLayout : VertexLayout.INTERLEAVED @@ -418,10 +418,10 @@ define([ var appendTextureCoordinatesQuaternion = new Quaternion(); var appendTextureCoordinatesMatrix3 = new Matrix3(); - function appendTextureCoordinates(tangentPlane, boundingRectangle, mesh, angle) { + function appendTextureCoordinates(tangentPlane, boundingRectangle, geometry, angle) { var origin = new Cartesian2(boundingRectangle.x, boundingRectangle.y); - var positions = mesh.attributes.position.values; + var positions = geometry.attributes.position.values; var length = positions.length; var textureCoordinates = new Float32Array(2 * (length / 3)); @@ -443,13 +443,13 @@ define([ textureCoordinates[j++] = st.y / boundingRectangle.height; } - mesh.attributes.textureCoordinates = { + geometry.attributes.textureCoordinates = { componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 2, values : textureCoordinates }; - return mesh; + return geometry; } var computeBoundingRectangleCartesian2 = new Cartesian2(); @@ -516,13 +516,13 @@ define([ if ((minX < 0) && (BoundingSphere.intersect(boundingSphere, Cartesian4.UNIT_Y) === Intersect.INTERSECTING)) { indices = PolygonPipeline.wrapLongitude(cleanedPositions, indices); } - var mesh = PolygonPipeline.computeSubdivision(cleanedPositions, indices, polygon._granularity); + var geometry = PolygonPipeline.computeSubdivision(cleanedPositions, indices, polygon._granularity); var boundary = outerPositions || cleanedPositions; var boundingRectangle = computeBoundingRectangle(tangentPlane, boundary, angle, createGeometryFromPositionsBoundingRectangle); - mesh = appendTextureCoordinates(tangentPlane, boundingRectangle, mesh, angle); + geometry = appendTextureCoordinates(tangentPlane, boundingRectangle, geometry, angle); return new GeometryInstance({ - geometry : mesh + geometry : geometry }); } @@ -530,13 +530,13 @@ define([ // PERFORMANCE_IDEA: Move this to a web-worker. var i; var geometries = []; - var mesh; + var geometry; if (typeof polygon._positions !== 'undefined') { polygon._boundingVolume = BoundingSphere.fromPoints(polygon._positions, polygon._boundingVolume); - mesh = createGeometryFromPositions(polygon, polygon._positions, polygon._textureRotationAngle, polygon._boundingVolume); - if (typeof mesh !== 'undefined') { - geometries.push(mesh); + geometry = createGeometryFromPositions(polygon, polygon._positions, polygon._textureRotationAngle, polygon._boundingVolume); + if (typeof geometry !== 'undefined') { + geometries.push(geometry); } } else if (typeof polygon._polygonHierarchy !== 'undefined') { var outerPositions = polygon._polygonHierarchy[0]; @@ -545,9 +545,9 @@ define([ // volume doesn't cover the polygon. polygon._boundingVolume = BoundingSphere.fromPoints(outerPositions, polygon._boundingVolume); for (i = 0; i < polygon._polygonHierarchy.length; i++) { - mesh = createGeometryFromPositions(polygon, polygon._polygonHierarchy[i], polygon._textureRotationAngle, polygon._boundingVolume, outerPositions); - if (typeof mesh !== 'undefined') { - geometries.push(mesh); + geometry = createGeometryFromPositions(polygon, polygon._polygonHierarchy[i], polygon._textureRotationAngle, polygon._boundingVolume, outerPositions); + if (typeof geometry !== 'undefined') { + geometries.push(geometry); } } } @@ -556,24 +556,24 @@ define([ return undefined; } - mesh = GeometryFilters.combine(geometries); - mesh = PolygonPipeline.scaleToGeodeticHeight(mesh, polygon.height, polygon.ellipsoid); - mesh = GeometryFilters.reorderForPostVertexCache(mesh); - mesh = GeometryFilters.reorderForPreVertexCache(mesh); + geometry = GeometryFilters.combine(geometries); + geometry = PolygonPipeline.scaleToGeodeticHeight(geometry, polygon.height, polygon.ellipsoid); + geometry = GeometryFilters.reorderForPostVertexCache(geometry); + geometry = GeometryFilters.reorderForPreVertexCache(geometry); if (polygon._mode === SceneMode.SCENE3D) { - mesh.attributes.position2DHigh = { // Not actually used in shader + geometry.attributes.position2DHigh = { // Not actually used in shader value : [0.0, 0.0] }; - mesh.attributes.position2DLow = { // Not actually used in shader + geometry.attributes.position2DLow = { // Not actually used in shader value : [0.0, 0.0] }; - mesh = GeometryFilters.encodeAttribute(mesh, 'position', 'position3DHigh', 'position3DLow'); + geometry = GeometryFilters.encodeAttribute(geometry, 'position', 'position3DHigh', 'position3DLow'); } else { - mesh = GeometryFilters.projectTo2D(mesh, polygon._projection); + geometry = GeometryFilters.projectTo2D(geometry, polygon._projection); if (polygon._mode !== SceneMode.SCENE3D) { - var projectedPositions = mesh.attributes.position2D.values; + var projectedPositions = geometry.attributes.position2D.values; var positions = []; for (var j = 0; j < projectedPositions.length; j += 2) { @@ -585,11 +585,11 @@ define([ polygon._boundingVolume2D.center = new Cartesian3(0.0, center2DPositions.x, center2DPositions.y); } - mesh = GeometryFilters.encodeAttribute(mesh, 'position3D', 'position3DHigh', 'position3DLow'); - mesh = GeometryFilters.encodeAttribute(mesh, 'position2D', 'position2DHigh', 'position2DLow'); + geometry = GeometryFilters.encodeAttribute(geometry, 'position3D', 'position3DHigh', 'position3DLow'); + geometry = GeometryFilters.encodeAttribute(geometry, 'position2D', 'position2DHigh', 'position2DLow'); } - return GeometryFilters.fitToUnsignedShortIndices(mesh); + return GeometryFilters.fitToUnsignedShortIndices(geometry); } function getGranularity(polygon, mode) { diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index edab76fc37e3..d86bfe0cc31b 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -360,7 +360,7 @@ define([ var va = []; for (i = 0; i < length; ++i) { va.push(context.createVertexArrayFromGeometry({ - mesh : geometries[i], + geometry : geometries[i], attributeIndices : attributeIndices, bufferUsage : BufferUsage.STATIC_DRAW, vertexLayout : VertexLayout.INTERLEAVED diff --git a/Source/Scene/SkyAtmosphere.js b/Source/Scene/SkyAtmosphere.js index 01b726f79407..03cc32e4470d 100644 --- a/Source/Scene/SkyAtmosphere.js +++ b/Source/Scene/SkyAtmosphere.js @@ -133,13 +133,13 @@ define([ var command = this._command; if (typeof command.vertexArray === 'undefined') { - var mesh = new EllipsoidGeometry({ + var geometry = new EllipsoidGeometry({ ellipsoid : Ellipsoid.fromCartesian3(this._ellipsoid.getRadii().multiplyByScalar(1.025)), numberOfPartitions : 60 }); command.vertexArray = context.createVertexArrayFromGeometry({ - mesh : mesh, - attributeIndices : GeometryFilters.createAttributeIndices(mesh), + geometry : geometry, + attributeIndices : GeometryFilters.createAttributeIndices(geometry), bufferUsage : BufferUsage.STATIC_DRAW }); command.primitiveType = PrimitiveType.TRIANGLES; diff --git a/Source/Scene/SkyBox.js b/Source/Scene/SkyBox.js index 1e73e7d13d43..421b4aa9072d 100644 --- a/Source/Scene/SkyBox.js +++ b/Source/Scene/SkyBox.js @@ -150,16 +150,16 @@ define([ } }; - var mesh = new BoxGeometry({ + var geometry = new BoxGeometry({ dimensions : new Cartesian3(2.0, 2.0, 2.0), vertexFormat : VertexFormat.POSITION_ONLY }); - var attributeIndices = GeometryFilters.createAttributeIndices(mesh); + var attributeIndices = GeometryFilters.createAttributeIndices(geometry); command.primitiveType = PrimitiveType.TRIANGLES; command.modelMatrix = Matrix4.IDENTITY.clone(); command.vertexArray = context.createVertexArrayFromGeometry({ - mesh: mesh, + geometry: geometry, attributeIndices: attributeIndices, bufferUsage: BufferUsage.STATIC_DRAW }); diff --git a/Source/Scene/SunPostProcess.js b/Source/Scene/SunPostProcess.js index 0883b334a3ff..5ddd024a2c7b 100644 --- a/Source/Scene/SunPostProcess.js +++ b/Source/Scene/SunPostProcess.js @@ -7,6 +7,8 @@ define([ '../Core/ComponentDatatype', '../Core/defaultValue', '../Core/destroyObject', + '../Core/Geometry', + '../Core/GeometryAttribute', '../Core/Math', '../Core/Matrix4', '../Core/PrimitiveType', @@ -31,6 +33,8 @@ define([ ComponentDatatype, defaultValue, destroyObject, + Geometry, + GeometryAttribute, CesiumMath, Matrix4, PrimitiveType, @@ -113,9 +117,9 @@ define([ return vertexArray; } - var mesh = { + var geometry = new Geometry({ attributes : { - position : { + position : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 2, values : [ @@ -124,9 +128,9 @@ define([ 1.0, 1.0, -1.0, 1.0 ] - }, + }), - textureCoordinates : { + textureCoordinates : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 2, values : [ @@ -135,12 +139,12 @@ define([ 1.0, 1.0, 0.0, 1.0 ] - } + }) } - }; + }); vertexArray = context.createVertexArrayFromGeometry({ - mesh : mesh, + geometry : geometry, attributeIndices : attributeIndices, bufferUsage : BufferUsage.STATIC_DRAW }); diff --git a/Source/Scene/ViewportQuad.js b/Source/Scene/ViewportQuad.js index 30408b7bb34f..ee63ea19a494 100644 --- a/Source/Scene/ViewportQuad.js +++ b/Source/Scene/ViewportQuad.js @@ -8,6 +8,8 @@ define([ '../Core/BoundingRectangle', '../Core/ComponentDatatype', '../Core/PrimitiveType', + '../Core/Geometry', + '../Core/GeometryAttribute', './Material', '../Renderer/BufferUsage', '../Renderer/BlendingState', @@ -24,6 +26,8 @@ define([ BoundingRectangle, ComponentDatatype, PrimitiveType, + Geometry, + GeometryAttribute, Material, BufferUsage, BlendingState, @@ -118,9 +122,9 @@ define([ return vertexArray; } - var mesh = { + var geometry = new Geometry({ attributes : { - position : { + position : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 2, values : [ @@ -129,9 +133,9 @@ define([ 1.0, 1.0, -1.0, 1.0 ] - }, + }), - textureCoordinates : { + textureCoordinates : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 2, values : [ @@ -140,12 +144,12 @@ define([ 1.0, 1.0, 0.0, 1.0 ] - } + }) } - }; + }); vertexArray = context.createVertexArrayFromGeometry({ - mesh : mesh, + geometry : geometry, attributeIndices : attributeIndices, bufferUsage : BufferUsage.STATIC_DRAW }); diff --git a/Specs/Core/GeometryFiltersSpec.js b/Specs/Core/GeometryFiltersSpec.js index e88158896f59..ac10d19d74e3 100644 --- a/Specs/Core/GeometryFiltersSpec.js +++ b/Specs/Core/GeometryFiltersSpec.js @@ -33,14 +33,14 @@ defineSuite([ /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/ it('converts triangles to wireframe in place', function() { - var mesh = GeometryFilters.toWireframe(new Geometry({ + var geometry = GeometryFilters.toWireframe(new Geometry({ indexList : [0, 1, 2, 3, 4, 5], primitiveType : PrimitiveType.TRIANGLES })); - expect(mesh.primitiveType).toEqual(PrimitiveType.LINES); + expect(geometry.primitiveType).toEqual(PrimitiveType.LINES); - var v = mesh.indexList; + var v = geometry.indexList; expect(v.length).toEqual(12); expect(v[0]).toEqual(0); @@ -59,14 +59,14 @@ defineSuite([ }); it('converts a triangle fan to wireframe in place', function() { - var mesh = GeometryFilters.toWireframe(new Geometry({ + var geometry = GeometryFilters.toWireframe(new Geometry({ indexList : [0, 1, 2, 3], primitiveType : PrimitiveType.TRIANGLE_FAN })); - expect(mesh.primitiveType).toEqual(PrimitiveType.LINES); + expect(geometry.primitiveType).toEqual(PrimitiveType.LINES); - var v = mesh.indexList; + var v = geometry.indexList; expect(v.length).toEqual(12); expect(v[0]).toEqual(0); @@ -85,14 +85,14 @@ defineSuite([ }); it('converts a triangle strip to wireframe in place', function() { - var mesh = GeometryFilters.toWireframe(new Geometry({ + var geometry = GeometryFilters.toWireframe(new Geometry({ indexList : [0, 1, 2, 3], primitiveType : PrimitiveType.TRIANGLE_STRIP })); - expect(mesh.primitiveType).toEqual(PrimitiveType.LINES); + expect(geometry.primitiveType).toEqual(PrimitiveType.LINES); - var v = mesh.indexList; + var v = geometry.indexList; expect(v.length).toEqual(12); expect(v[0]).toEqual(0); @@ -111,7 +111,7 @@ defineSuite([ }); it('creates attribute indices', function() { - var mesh = new Geometry({ + var geometry = new Geometry({ attributes : { position : new GeometryAttribute(), normal : new GeometryAttribute(), @@ -119,7 +119,7 @@ defineSuite([ } }); - var indices = GeometryFilters.createAttributeIndices(mesh); + var indices = GeometryFilters.createAttributeIndices(geometry); var validIndices = [0, 1, 2]; expect(validIndices).toContain(indices.position); @@ -147,9 +147,9 @@ defineSuite([ expect(mappedIndices.color).toEqual(indices.colors); }); - it('throws an exception when mesh properties have a different number of attributes', function() { + it('throws an exception when geometry properties have a different number of attributes', function() { expect(function() { - var mesh = new Geometry({ + var geometry = new Geometry({ attributes : { attribute1 : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, @@ -164,12 +164,12 @@ defineSuite([ } }); - mesh = GeometryFilters.reorderForPreVertexCache(mesh); + geometry = GeometryFilters.reorderForPreVertexCache(geometry); }).toThrow(); }); it('can reorder all indices and attributes for the pre vertex cahce', function() { - var mesh = new Geometry({ + var geometry = new Geometry({ attributes : { weight : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, @@ -186,54 +186,54 @@ defineSuite([ primitiveType : PrimitiveType.TRIANGLES }); - GeometryFilters.reorderForPreVertexCache(mesh); - - expect(mesh.indexList[0]).toEqual(0); - expect(mesh.indexList[1]).toEqual(1); - expect(mesh.indexList[2]).toEqual(2); - expect(mesh.indexList[3]).toEqual(3); - expect(mesh.indexList[4]).toEqual(4); - expect(mesh.indexList[5]).toEqual(5); - expect(mesh.indexList[6]).toEqual(5); - expect(mesh.indexList[7]).toEqual(4); - expect(mesh.indexList[8]).toEqual(1); - expect(mesh.indexList[9]).toEqual(2); - expect(mesh.indexList[10]).toEqual(0); - expect(mesh.indexList[11]).toEqual(3); - - expect(mesh.attributes.weight.values[0]).toEqual(5.0); - expect(mesh.attributes.weight.values[1]).toEqual(3.0); - expect(mesh.attributes.weight.values[2]).toEqual(2.0); - expect(mesh.attributes.weight.values[3]).toEqual(0.0); - expect(mesh.attributes.weight.values[4]).toEqual(1.0); - expect(mesh.attributes.weight.values[5]).toEqual(4.0); - - expect(mesh.attributes.positions.values[0]).toEqual(15); - expect(mesh.attributes.positions.values[1]).toEqual(16); - expect(mesh.attributes.positions.values[2]).toEqual(17); - expect(mesh.attributes.positions.values[3]).toEqual(9); - expect(mesh.attributes.positions.values[4]).toEqual(10); - expect(mesh.attributes.positions.values[5]).toEqual(11); - expect(mesh.attributes.positions.values[6]).toEqual(6); - expect(mesh.attributes.positions.values[7]).toEqual(7); - expect(mesh.attributes.positions.values[8]).toEqual(8); - expect(mesh.attributes.positions.values[9]).toEqual(0); - expect(mesh.attributes.positions.values[10]).toEqual(1); - expect(mesh.attributes.positions.values[11]).toEqual(2); - expect(mesh.attributes.positions.values[12]).toEqual(3); - expect(mesh.attributes.positions.values[13]).toEqual(4); - expect(mesh.attributes.positions.values[14]).toEqual(5); - expect(mesh.attributes.positions.values[15]).toEqual(12); - expect(mesh.attributes.positions.values[16]).toEqual(13); - expect(mesh.attributes.positions.values[17]).toEqual(14); + GeometryFilters.reorderForPreVertexCache(geometry); + + expect(geometry.indexList[0]).toEqual(0); + expect(geometry.indexList[1]).toEqual(1); + expect(geometry.indexList[2]).toEqual(2); + expect(geometry.indexList[3]).toEqual(3); + expect(geometry.indexList[4]).toEqual(4); + expect(geometry.indexList[5]).toEqual(5); + expect(geometry.indexList[6]).toEqual(5); + expect(geometry.indexList[7]).toEqual(4); + expect(geometry.indexList[8]).toEqual(1); + expect(geometry.indexList[9]).toEqual(2); + expect(geometry.indexList[10]).toEqual(0); + expect(geometry.indexList[11]).toEqual(3); + + expect(geometry.attributes.weight.values[0]).toEqual(5.0); + expect(geometry.attributes.weight.values[1]).toEqual(3.0); + expect(geometry.attributes.weight.values[2]).toEqual(2.0); + expect(geometry.attributes.weight.values[3]).toEqual(0.0); + expect(geometry.attributes.weight.values[4]).toEqual(1.0); + expect(geometry.attributes.weight.values[5]).toEqual(4.0); + + expect(geometry.attributes.positions.values[0]).toEqual(15); + expect(geometry.attributes.positions.values[1]).toEqual(16); + expect(geometry.attributes.positions.values[2]).toEqual(17); + expect(geometry.attributes.positions.values[3]).toEqual(9); + expect(geometry.attributes.positions.values[4]).toEqual(10); + expect(geometry.attributes.positions.values[5]).toEqual(11); + expect(geometry.attributes.positions.values[6]).toEqual(6); + expect(geometry.attributes.positions.values[7]).toEqual(7); + expect(geometry.attributes.positions.values[8]).toEqual(8); + expect(geometry.attributes.positions.values[9]).toEqual(0); + expect(geometry.attributes.positions.values[10]).toEqual(1); + expect(geometry.attributes.positions.values[11]).toEqual(2); + expect(geometry.attributes.positions.values[12]).toEqual(3); + expect(geometry.attributes.positions.values[13]).toEqual(4); + expect(geometry.attributes.positions.values[14]).toEqual(5); + expect(geometry.attributes.positions.values[15]).toEqual(12); + expect(geometry.attributes.positions.values[16]).toEqual(13); + expect(geometry.attributes.positions.values[17]).toEqual(14); }); it('can reorder indices for the post vertex cache', function() { - var mesh = new EllipsoidGeometry({ + var geometry = new EllipsoidGeometry({ ellipsoid : new Ellipsoid(10.0, 10.0, 10.0), numberOfPartitions : 100 }); - var indices = mesh.indexList; + var indices = geometry.indexList; var numIndices = indices.length; var maximumIndex = 0; for ( var i = 0; i < numIndices; i++) { @@ -245,16 +245,16 @@ defineSuite([ maximumIndex : maximumIndex, cacheSize : 24}); expect(ACMRbefore).toBeGreaterThan(1.00); - mesh = GeometryFilters.reorderForPostVertexCache(mesh); - indices = mesh.indexList; + geometry = GeometryFilters.reorderForPostVertexCache(geometry); + indices = geometry.indexList; var ACMRafter = Tipsify.calculateACMR({indices : indices, maximumIndex : maximumIndex, cacheSize : 24}); expect(ACMRafter).toBeLessThan(0.70); }); - it('fitToUnsignedShortIndices does not change mesh', function() { - var mesh = new Geometry({ + it('fitToUnsignedShortIndices does not change geometry', function() { + var geometry = new Geometry({ attributes : { time : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, @@ -271,20 +271,20 @@ defineSuite([ primitiveType : PrimitiveType.TRIANGLES }); - var geometries = GeometryFilters.fitToUnsignedShortIndices(mesh); + var geometries = GeometryFilters.fitToUnsignedShortIndices(geometry); expect(geometries.length).toEqual(1); - expect(geometries[0]).toBe(mesh); + expect(geometries[0]).toBe(geometry); }); - it('fitToUnsignedShortIndices creates one mesh', function() { + it('fitToUnsignedShortIndices creates one geometry', function() { var sixtyFourK = 64 * 1024; var times = []; for ( var i = 0; i < sixtyFourK + 1; ++i) { times.push(i); } - var mesh = new Geometry({ + var geometry = new Geometry({ attributes : { time : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, @@ -296,7 +296,7 @@ defineSuite([ primitiveType : PrimitiveType.TRIANGLES }); - var geometries = GeometryFilters.fitToUnsignedShortIndices(mesh); + var geometries = GeometryFilters.fitToUnsignedShortIndices(geometry); expect(geometries.length).toEqual(1); expect(geometries[0].attributes.time.componentDatatype).toEqual(ComponentDatatype.FLOAT); @@ -321,7 +321,7 @@ defineSuite([ } indices.push(0, 1, 2); - var mesh = new Geometry({ + var geometry = new Geometry({ attributes : { position : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, @@ -333,7 +333,7 @@ defineSuite([ primitiveType : PrimitiveType.TRIANGLES }); - var geometries = GeometryFilters.fitToUnsignedShortIndices(mesh); + var geometries = GeometryFilters.fitToUnsignedShortIndices(geometry); expect(geometries.length).toEqual(2); @@ -345,7 +345,7 @@ defineSuite([ }); it('fitToUnsignedShortIndices throws without triangles', function() { - var mesh = new Geometry({ + var geometry = new Geometry({ attributes : { time : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, @@ -358,12 +358,12 @@ defineSuite([ }); expect(function() { - return GeometryFilters.fitToUnsignedShortIndices(mesh); + return GeometryFilters.fitToUnsignedShortIndices(geometry); }).toThrow(); }); it('fitToUnsignedShortIndices throws with different numbers of attributes', function() { - var mesh = new Geometry({ + var geometry = new Geometry({ attributes : { time : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, @@ -381,7 +381,7 @@ defineSuite([ }); expect(function() { - return GeometryFilters.fitToUnsignedShortIndices(mesh); + return GeometryFilters.fitToUnsignedShortIndices(geometry); }).toThrow(); }); @@ -389,39 +389,39 @@ defineSuite([ var p1 = new Cartesian3(100000, 200000, 300000); var p2 = new Cartesian3(400000, 500000, 600000); - var mesh = {}; - mesh.attributes = {}; - mesh.attributes.position = { + var geometry = {}; + geometry.attributes = {}; + geometry.attributes.position = { componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 3, values : [p1.x, p1.y, p1.z, p2.x, p2.y, p2.z] }; - mesh = GeometryFilters.projectTo2D(mesh); + geometry = GeometryFilters.projectTo2D(geometry); var ellipsoid = Ellipsoid.WGS84; var projection = new GeographicProjection(); var projectedP1 = projection.project(ellipsoid.cartesianToCartographic(p1)); var projectedP2 = projection.project(ellipsoid.cartesianToCartographic(p2)); - expect(mesh.attributes.position2D.values[0]).toEqual(projectedP1.x); - expect(mesh.attributes.position2D.values[1]).toEqual(projectedP1.y); - expect(mesh.attributes.position2D.values[2]).toEqual(projectedP2.x); - expect(mesh.attributes.position2D.values[3]).toEqual(projectedP2.y); - - expect(mesh.attributes.position3D.values[0]).toEqual(p1.x); - expect(mesh.attributes.position3D.values[1]).toEqual(p1.y); - expect(mesh.attributes.position3D.values[2]).toEqual(p1.z); - expect(mesh.attributes.position3D.values[3]).toEqual(p2.x); - expect(mesh.attributes.position3D.values[4]).toEqual(p2.y); - expect(mesh.attributes.position3D.values[5]).toEqual(p2.z); + expect(geometry.attributes.position2D.values[0]).toEqual(projectedP1.x); + expect(geometry.attributes.position2D.values[1]).toEqual(projectedP1.y); + expect(geometry.attributes.position2D.values[2]).toEqual(projectedP2.x); + expect(geometry.attributes.position2D.values[3]).toEqual(projectedP2.y); + + expect(geometry.attributes.position3D.values[0]).toEqual(p1.x); + expect(geometry.attributes.position3D.values[1]).toEqual(p1.y); + expect(geometry.attributes.position3D.values[2]).toEqual(p1.z); + expect(geometry.attributes.position3D.values[3]).toEqual(p2.x); + expect(geometry.attributes.position3D.values[4]).toEqual(p2.y); + expect(geometry.attributes.position3D.values[5]).toEqual(p2.z); }); it('GeometryFilters.encodeAttribute encodes positions', function() { var c = new Cartesian3(-10000000.0, 0.0, 10000000.0); var encoded = EncodedCartesian3.fromCartesian(c); - var mesh = new Geometry({ + var geometry = new Geometry({ attributes : { position : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, @@ -430,26 +430,26 @@ defineSuite([ }) } }); - mesh = GeometryFilters.encodeAttribute(mesh); - - expect(mesh.attributes.positionHigh).toBeDefined(); - expect(mesh.attributes.positionHigh.values[0]).toEqual(encoded.high.x); - expect(mesh.attributes.positionHigh.values[1]).toEqual(encoded.high.y); - expect(mesh.attributes.positionHigh.values[2]).toEqual(encoded.high.z); - expect(mesh.attributes.positionLow).toBeDefined(); - expect(mesh.attributes.positionLow.values[0]).toEqual(encoded.low.x); - expect(mesh.attributes.positionLow.values[1]).toEqual(encoded.low.y); - expect(mesh.attributes.positionLow.values[2]).toEqual(encoded.low.z); - expect(mesh.attributes.position).not.toBeDefined(); + geometry = GeometryFilters.encodeAttribute(geometry); + + expect(geometry.attributes.positionHigh).toBeDefined(); + expect(geometry.attributes.positionHigh.values[0]).toEqual(encoded.high.x); + expect(geometry.attributes.positionHigh.values[1]).toEqual(encoded.high.y); + expect(geometry.attributes.positionHigh.values[2]).toEqual(encoded.high.z); + expect(geometry.attributes.positionLow).toBeDefined(); + expect(geometry.attributes.positionLow.values[0]).toEqual(encoded.low.x); + expect(geometry.attributes.positionLow.values[1]).toEqual(encoded.low.y); + expect(geometry.attributes.positionLow.values[2]).toEqual(encoded.low.z); + expect(geometry.attributes.position).not.toBeDefined(); }); - it('GeometryFilters.encodeAttribute throws without a mesh', function() { + it('GeometryFilters.encodeAttribute throws without a geometry', function() { expect(function() { GeometryFilters.encodeAttribute(undefined); }).toThrow(); }); - it('GeometryFilters.encodeAttribute throws with mesh without attributes property', function() { + it('GeometryFilters.encodeAttribute throws with geometry without attributes property', function() { expect(function() { GeometryFilters.encodeAttribute({}); }).toThrow(); @@ -463,18 +463,18 @@ defineSuite([ it('GeometryFilters.encodeAttribute throws without ComponentDatatype.FLOAT', function() { expect(function() { - var mesh = new Geometry({ + var geometry = new Geometry({ attributes : new GeometryAttribute({ componentDatatype : ComponentDatatype.UNSIGNED_SHORT, componentsPerAttribute : 1, values : [0.0] }) }); - GeometryFilters.encodeAttribute(mesh); + GeometryFilters.encodeAttribute(geometry); }).toThrow(); }); - it('GeometryFilters.combine combines one mesh', function() { + it('GeometryFilters.combine combines one geometry', function() { var instance = new GeometryInstance({ geometry : new Geometry({ attributes : new GeometryAttribute({ @@ -569,19 +569,19 @@ defineSuite([ }).toThrow(); }); - it('GeometryFilters.computeNormal throws when mesh is undefined', function() { + it('GeometryFilters.computeNormal throws when geometry is undefined', function() { expect(function() { GeometryFilters.computeNormal(); }).toThrow(); }); - it('GeometryFilters.computeNormal throws when mesh.attributes.position is undefined', function() { + it('GeometryFilters.computeNormal throws when geometry.attributes.position is undefined', function() { expect(function() { GeometryFilters.computeNormal(new Geometry()); }).toThrow(); }); - it('GeometryFilters.computeNormal throws when mesh.attributes.position.values is undefined', function() { + it('GeometryFilters.computeNormal throws when geometry.attributes.position.values is undefined', function() { expect(function() { GeometryFilters.computeNormal(new Geometry({ attributes: { @@ -591,7 +591,7 @@ defineSuite([ }).toThrow(); }); - it('GeometryFilters.computeNormal throws when mesh.attributes.position.componentsPerAttribute is not 3', function() { + it('GeometryFilters.computeNormal throws when geometry.attributes.position.componentsPerAttribute is not 3', function() { expect(function() { GeometryFilters.computeNormal(new Geometry({ attributes: { @@ -604,7 +604,7 @@ defineSuite([ }).toThrow(); }); - it('GeometryFilters.computeNormal throws when mesh.attributes.position.values is not a multiple of 3', function() { + it('GeometryFilters.computeNormal throws when geometry.attributes.position.values is not a multiple of 3', function() { expect(function() { GeometryFilters.computeNormal(new Geometry( { attributes: { @@ -617,8 +617,8 @@ defineSuite([ }).toThrow(); }); - it('GeometryFilters.computeNormal does not compute normals when mesh.indexList is undefined', function() { - var mesh = new Geometry({ + it('GeometryFilters.computeNormal does not compute normals when geometry.indexList is undefined', function() { + var geometry = new Geometry({ attributes: { position: new GeometryAttribute({ values: [0, 0, 0, 1, 0, 0, 0, 1, 0], @@ -627,13 +627,13 @@ defineSuite([ } }); - mesh = GeometryFilters.computeNormal(mesh); + geometry = GeometryFilters.computeNormal(geometry); - expect(typeof mesh.attributes.normal === 'undefined').toEqual(true); + expect(typeof geometry.attributes.normal === 'undefined').toEqual(true); }); it('GeometryFilters.computeNormal does not compute normals when primitive type is not triangle', function() { - var mesh = new Geometry({ + var geometry = new Geometry({ attributes: { position: new GeometryAttribute({ values: [0, 0, 0, 1, 0, 0, 0, 1, 0], @@ -644,14 +644,14 @@ defineSuite([ primitiveType: PrimitiveType.TRIANGLE_STRIP }); - mesh = GeometryFilters.computeNormal(mesh); + geometry = GeometryFilters.computeNormal(geometry); - expect(typeof mesh.attributes.normal === 'undefined').toEqual(true); + expect(typeof geometry.attributes.normal === 'undefined').toEqual(true); }); it('GeometryFilters.computeNormal computes normal for one triangle', function() { - var mesh = new Geometry({ + var geometry = new Geometry({ attributes: { position: new GeometryAttribute({ values: [0, 0, 0, 1, 0, 0, 0, 1, 0], @@ -662,14 +662,14 @@ defineSuite([ primitiveType: PrimitiveType.TRIANGLES }); - mesh = GeometryFilters.computeNormal(mesh); + geometry = GeometryFilters.computeNormal(geometry); - expect(mesh.attributes.normal.values.length).toEqual(3*3); - expect(mesh.attributes.normal.values).toEqual([0, 0, 1, 0, 0, 1, 0, 0, 1]); + expect(geometry.attributes.normal.values.length).toEqual(3*3); + expect(geometry.attributes.normal.values).toEqual([0, 0, 1, 0, 0, 1, 0, 0, 1]); }); it('GeometryFilters.computeNormal computes normal for two triangles', function() { - var mesh = new Geometry({ + var geometry = new Geometry({ attributes: { position: new GeometryAttribute({ values: [0, 0, 0, 1, 0, 1, 1, 1, 1, 2, 0, 0], @@ -680,18 +680,18 @@ defineSuite([ primitiveType: PrimitiveType.TRIANGLES }); - mesh = GeometryFilters.computeNormal(mesh); + geometry = GeometryFilters.computeNormal(geometry); - expect(mesh.attributes.normal.values.length).toEqual(4*3); + expect(geometry.attributes.normal.values.length).toEqual(4*3); var a = new Cartesian3(-1, 0, 1).normalize(); - expect(mesh.attributes.normal.values.slice(0, 3)).toEqual([a.x, a.y, a.z]); - expect(mesh.attributes.normal.values.slice(3, 9)).toEqual([0, 0, 1, 0, 0, 1]); + expect(geometry.attributes.normal.values.slice(0, 3)).toEqual([a.x, a.y, a.z]); + expect(geometry.attributes.normal.values.slice(3, 9)).toEqual([0, 0, 1, 0, 0, 1]); a = new Cartesian3(1, 0, 1).normalize(); - expect(mesh.attributes.normal.values.slice(9, 12)).toEqual([a.x, a.y, a.z]); + expect(geometry.attributes.normal.values.slice(9, 12)).toEqual([a.x, a.y, a.z]); }); it('GeometryFilters.computeNormal computes normal for six triangles', function() { - var mesh = new Geometry ({ + var geometry = new Geometry ({ attributes: { position: new GeometryAttribute({ values: [0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0], @@ -702,29 +702,29 @@ defineSuite([ primitiveType: PrimitiveType.TRIANGLES }); - mesh = GeometryFilters.computeNormal(mesh); + geometry = GeometryFilters.computeNormal(geometry); - expect(mesh.attributes.normal.values.length).toEqual(7*3); + expect(geometry.attributes.normal.values.length).toEqual(7*3); var a = new Cartesian3(-1, -1, -1).normalize(); - expect(mesh.attributes.normal.values.slice(0, 3)).toEqual([a.x, a.y, a.z]); + expect(geometry.attributes.normal.values.slice(0, 3)).toEqual([a.x, a.y, a.z]); a = new Cartesian3(0, -1, -1).normalize(); - expect(mesh.attributes.normal.values.slice(3, 6)).toEqual([a.x, a.y, a.z]); - expect(mesh.attributes.normal.values.slice(6, 9)).toEqual([0, -1, 0]); + expect(geometry.attributes.normal.values.slice(3, 6)).toEqual([a.x, a.y, a.z]); + expect(geometry.attributes.normal.values.slice(6, 9)).toEqual([0, -1, 0]); a = new Cartesian3(-1, -1, 0).normalize(); - expect(mesh.attributes.normal.values.slice(9, 12)).toEqual([a.x, a.y, a.z]); - expect(mesh.attributes.normal.values.slice(12, 15)).toEqual([-1, 0, 0]); + expect(geometry.attributes.normal.values.slice(9, 12)).toEqual([a.x, a.y, a.z]); + expect(geometry.attributes.normal.values.slice(12, 15)).toEqual([-1, 0, 0]); a = new Cartesian3(-1, 0, -1).normalize(); - expect(mesh.attributes.normal.values.slice(15,18)).toEqual([a.x, a.y, a.z]); - expect(mesh.attributes.normal.values.slice(18,21)).toEqual([0, 0, -1]); + expect(geometry.attributes.normal.values.slice(15,18)).toEqual([a.x, a.y, a.z]); + expect(geometry.attributes.normal.values.slice(18,21)).toEqual([0, 0, -1]); }); - it('GeometryFilters.computeTangentAndBinormal throws when mesh is undefined', function() { + it('GeometryFilters.computeTangentAndBinormal throws when geometry is undefined', function() { expect(function() { GeometryFilters.computeTangentAndBinormal(); }).toThrow(); }); - it('GeometryFilters.computeTangentAndBinormal throws when mesh.attributes.position is undefined', function() { + it('GeometryFilters.computeTangentAndBinormal throws when geometry.attributes.position is undefined', function() { expect(function() { GeometryFilters.computeTangentAndBinormal(new Geometry({ attributes: {} @@ -732,7 +732,7 @@ defineSuite([ }).toThrow(); }); - it('GeometryFilters.computeTangentAndBinormal throws when mesh.attributes.position.values is undefined', function() { + it('GeometryFilters.computeTangentAndBinormal throws when geometry.attributes.position.values is undefined', function() { expect(function() { GeometryFilters.computeTangentAndBinormal(new Geometry({ attributes: { @@ -742,7 +742,7 @@ defineSuite([ }).toThrow(); }); - it('GeometryFilters.computeTangentAndBinormal throws when mesh.attributes.position.componentsPerAttribute is not 3', function() { + it('GeometryFilters.computeTangentAndBinormal throws when geometry.attributes.position.componentsPerAttribute is not 3', function() { expect(function() { GeometryFilters.computeTangentAndBinormal(new Geometry({ attributes: { @@ -755,7 +755,7 @@ defineSuite([ }).toThrow(); }); - it('GeometryFilters.computeTangentAndBinormal throws when mesh.attributes.position.values is not a multiple of 3', function() { + it('GeometryFilters.computeTangentAndBinormal throws when geometry.attributes.position.values is not a multiple of 3', function() { expect(function() { GeometryFilters.computeTangentAndBinormal(new Geometry({ attributes: { @@ -768,7 +768,7 @@ defineSuite([ }).toThrow(); }); - it('GeometryFilters.computeTangentAndBinormal throws when mesh.attributes.normal is undefined', function() { + it('GeometryFilters.computeTangentAndBinormal throws when geometry.attributes.normal is undefined', function() { expect(function() { GeometryFilters.computeTangentAndBinormal(new Geometry({ attributes: { @@ -781,7 +781,7 @@ defineSuite([ }).toThrow(); }); - it('GeometryFilters.computeTangentAndBinormal throws when mesh.attributes.normal.values is undefined', function() { + it('GeometryFilters.computeTangentAndBinormal throws when geometry.attributes.normal.values is undefined', function() { expect(function() { GeometryFilters.computeTangentAndBinormal(new Geometry({ attributes: { @@ -795,7 +795,7 @@ defineSuite([ }).toThrow(); }); - it('GeometryFilters.computeTangentAndBinormal throws when mesh.attributes.normal.componentsPerAttribute is not 3', function() { + it('GeometryFilters.computeTangentAndBinormal throws when geometry.attributes.normal.componentsPerAttribute is not 3', function() { expect(function() { GeometryFilters.computeTangentAndBinormal(new Geometry({ attributes: { @@ -812,7 +812,7 @@ defineSuite([ }).toThrow(); }); - it('GeometryFilters.computeTangentAndBinormal throws when mesh.attributes.normal.values is not a multiple of 3', function() { + it('GeometryFilters.computeTangentAndBinormal throws when geometry.attributes.normal.values is not a multiple of 3', function() { expect(function() { GeometryFilters.computeTangentAndBinormal(new Geometry({ attributes: { @@ -829,7 +829,7 @@ defineSuite([ }).toThrow(); }); - it('GeometryFilters.computeTangentAndBinormal throws when mesh.attributes.st is undefined', function() { + it('GeometryFilters.computeTangentAndBinormal throws when geometry.attributes.st is undefined', function() { expect(function() { GeometryFilters.computeTangentAndBinormal(new Geometry( { attributes: { @@ -847,7 +847,7 @@ defineSuite([ }).toThrow(); }); - it('GeometryFilters.computeTangentAndBinormal throws when mesh.attributes.normal.values is undefined', function() { + it('GeometryFilters.computeTangentAndBinormal throws when geometry.attributes.normal.values is undefined', function() { expect(function() { GeometryFilters.computeTangentAndBinormal(new Geometry( { attributes: { @@ -865,7 +865,7 @@ defineSuite([ }).toThrow(); }); - it('GeometryFilters.computeTangentAndBinormal throws when mesh.attributes.st.componentsPerAttribute is not 2', function() { + it('GeometryFilters.computeTangentAndBinormal throws when geometry.attributes.st.componentsPerAttribute is not 2', function() { expect(function() { GeometryFilters.computeTangentAndBinormal(new Geometry( { attributes: { @@ -886,7 +886,7 @@ defineSuite([ }).toThrow(); }); - it('GeometryFilters.computeTangentAndBinormal throws when mesh.attributes.st.values is not a multiple of 2', function() { + it('GeometryFilters.computeTangentAndBinormal throws when geometry.attributes.st.values is not a multiple of 2', function() { expect(function() { GeometryFilters.computeTangentAndBinormal(new Geometry( { attributes: { @@ -907,8 +907,8 @@ defineSuite([ }).toThrow(); }); - it('GeometryFilters.computeTangentAndBinormal does not compute tangent and binormals when mesh.indexList is undefined', function() { - var mesh = new Geometry({ + it('GeometryFilters.computeTangentAndBinormal does not compute tangent and binormals when geometry.indexList is undefined', function() { + var geometry = new Geometry({ attributes: { position: new GeometryAttribute({ values: [0, 0, 0, 1, 0, 0, 0, 1, 0], @@ -926,14 +926,14 @@ defineSuite([ } }); - mesh = GeometryFilters.computeTangentAndBinormal(mesh); + geometry = GeometryFilters.computeTangentAndBinormal(geometry); - expect(typeof mesh.attributes.tangent === 'undefined').toEqual(true); - expect(typeof mesh.attributes.binormal === 'undefined').toEqual(true); + expect(typeof geometry.attributes.tangent === 'undefined').toEqual(true); + expect(typeof geometry.attributes.binormal === 'undefined').toEqual(true); }); it('GeometryFilters.computeTangentAndBinormal does not compute tangent and binormals when primitive type is not triangle', function() { - var mesh = new Geometry({ + var geometry = new Geometry({ attributes: { position: new GeometryAttribute({ values: [0, 0, 0, 1, 0, 0, 0, 1, 0], @@ -954,14 +954,14 @@ defineSuite([ primitiveType: PrimitiveType.TRIANGLE_STRIP }); - mesh = GeometryFilters.computeTangentAndBinormal(mesh); + geometry = GeometryFilters.computeTangentAndBinormal(geometry); - expect(typeof mesh.attributes.tangent === 'undefined').toEqual(true); - expect(typeof mesh.attributes.binormal === 'undefined').toEqual(true); + expect(typeof geometry.attributes.tangent === 'undefined').toEqual(true); + expect(typeof geometry.attributes.binormal === 'undefined').toEqual(true); }); it('GeometryFilters.computeTangentAndBinormal computes tangent and binormal for one triangle', function() { - var mesh = new Geometry({ + var geometry = new Geometry({ attributes: { position: new GeometryAttribute({ values: [0, 0, 0, 1, 0, 0, 0, 1, 0], @@ -976,15 +976,15 @@ defineSuite([ primitiveType: PrimitiveType.TRIANGLES }); - mesh = GeometryFilters.computeNormal(mesh); - mesh = GeometryFilters.computeTangentAndBinormal(mesh); + geometry = GeometryFilters.computeNormal(geometry); + geometry = GeometryFilters.computeTangentAndBinormal(geometry); - expect(mesh.attributes.tangent.values).toEqual([1, 0, 0, 1, 0, 0, 1, 0, 0]); - expect(mesh.attributes.binormal.values).toEqual([0, 1, 0, 0, 1, 0, 0, 1, 0]); + expect(geometry.attributes.tangent.values).toEqual([1, 0, 0, 1, 0, 0, 1, 0, 0]); + expect(geometry.attributes.binormal.values).toEqual([0, 1, 0, 0, 1, 0, 0, 1, 0]); }); it('GeometryFilters.computeTangentAndBinormal computes tangent and binormal for two triangles', function() { - var mesh = new Geometry({ + var geometry = new Geometry({ attributes: { position: new GeometryAttribute({ values: [0, 0, 0, 1, 0, 1, 1, 1, 1, 2, 0, 0], @@ -999,26 +999,26 @@ defineSuite([ primitiveType: PrimitiveType.TRIANGLES }); - mesh = GeometryFilters.computeNormal(mesh); - mesh = GeometryFilters.computeTangentAndBinormal(mesh); - expect(mesh.attributes.tangent.values).toEqualEpsilon([0.7071067811865475, 0, 0.7071067811865475, + geometry = GeometryFilters.computeNormal(geometry); + geometry = GeometryFilters.computeTangentAndBinormal(geometry); + expect(geometry.attributes.tangent.values).toEqualEpsilon([0.7071067811865475, 0, 0.7071067811865475, 0, 1, 0, 0, 1, 0, -0.5773502691896258, 0.5773502691896258, 0.5773502691896258], CesiumMath.EPSILON8); - expect(mesh.attributes.binormal.values).toEqualEpsilon([0, 1, 0, + expect(geometry.attributes.binormal.values).toEqualEpsilon([0, 1, 0, -1, 0, 0, -1, 0, 0, -0.4082482904638631, -0.8164965809277261, 0.4082482904638631], CesiumMath.EPSILON8); }); it ('GeometryFilters.computeTangentAndBinormal computes tangent and binormal for an EllipsoidGeometry', function() { - var mesh = new EllipsoidGeometry(); + var geometry = new EllipsoidGeometry(); var expected = new EllipsoidGeometry({ vertexFormat: VertexFormat.ALL }); - mesh = GeometryFilters.computeTangentAndBinormal(mesh); - expect(mesh.attributes.tangent.values.slice(1000,1200)).toEqualEpsilon(expected.attributes.tangent.values.slice(1000,1200), CesiumMath.EPSILON1); - expect(mesh.attributes.binormal.values.slice(1000,1200)).toEqualEpsilon(expected.attributes.binormal.values.slice(1000,1200), CesiumMath.EPSILON1); + geometry = GeometryFilters.computeTangentAndBinormal(geometry); + expect(geometry.attributes.tangent.values.slice(1000,1200)).toEqualEpsilon(expected.attributes.tangent.values.slice(1000,1200), CesiumMath.EPSILON1); + expect(geometry.attributes.binormal.values.slice(1000,1200)).toEqualEpsilon(expected.attributes.binormal.values.slice(1000,1200), CesiumMath.EPSILON1); }); }); \ No newline at end of file diff --git a/Specs/Renderer/VertexArrayFactorySpec.js b/Specs/Renderer/VertexArrayFactorySpec.js index 39be0f336297..960ed039dacc 100644 --- a/Specs/Renderer/VertexArrayFactorySpec.js +++ b/Specs/Renderer/VertexArrayFactorySpec.js @@ -49,7 +49,7 @@ defineSuite([ expect(va.getIndexBuffer()).not.toBeDefined(); }); - it('creates with no mesh', function() { + it('creates with no geometry', function() { va = context.createVertexArrayFromGeometry({ vertexLayout : VertexLayout.INTERLEAVED }); @@ -58,7 +58,7 @@ defineSuite([ }); it('creates a single-attribute vertex (non-interleaved)', function() { - var mesh = new Geometry({ + var geometry = new Geometry({ attributes : { position : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, @@ -69,14 +69,14 @@ defineSuite([ }); var va = context.createVertexArrayFromGeometry({ - mesh : mesh, - attributeIndices : GeometryFilters.createAttributeIndices(mesh) + geometry : geometry, + attributeIndices : GeometryFilters.createAttributeIndices(geometry) }); expect(va.getNumberOfAttributes()).toEqual(1); expect(va.getIndexBuffer()).not.toBeDefined(); - var position = mesh.attributes.position; + var position = geometry.attributes.position; expect(va.getAttribute(0).index).toEqual(0); expect(va.getAttribute(0).componentDatatype).toEqual(position.componentDatatype); expect(va.getAttribute(0).componentsPerAttribute).toEqual(position.componentsPerAttribute); @@ -87,7 +87,7 @@ defineSuite([ }); it('creates a single-attribute vertex (interleaved)', function() { - var mesh = new Geometry({ + var geometry = new Geometry({ attributes : { position : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, @@ -98,8 +98,8 @@ defineSuite([ }); var va = context.createVertexArrayFromGeometry({ - mesh : mesh, - attributeIndices : GeometryFilters.createAttributeIndices(mesh), + geometry : geometry, + attributeIndices : GeometryFilters.createAttributeIndices(geometry), vertexLayout : VertexLayout.INTERLEAVED, bufferUsage : BufferUsage.STATIC_DRAW }); @@ -107,7 +107,7 @@ defineSuite([ expect(va.getNumberOfAttributes()).toEqual(1); expect(va.getIndexBuffer()).not.toBeDefined(); - var position = mesh.attributes.position; + var position = geometry.attributes.position; expect(va.getAttribute(0).index).toEqual(0); expect(va.getAttribute(0).componentDatatype).toEqual(position.componentDatatype); expect(va.getAttribute(0).componentsPerAttribute).toEqual(position.componentsPerAttribute); @@ -118,7 +118,7 @@ defineSuite([ }); it('creates a homogeneous multiple-attribute vertex (non-interleaved)', function() { - var mesh = new Geometry({ + var geometry = new Geometry({ attributes : { position : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, @@ -134,21 +134,21 @@ defineSuite([ }); var va = context.createVertexArrayFromGeometry({ - mesh : mesh, - attributeIndices : GeometryFilters.createAttributeIndices(mesh) + geometry : geometry, + attributeIndices : GeometryFilters.createAttributeIndices(geometry) }); expect(va.getNumberOfAttributes()).toEqual(2); expect(va.getIndexBuffer()).not.toBeDefined(); - var position = mesh.attributes.position; + var position = geometry.attributes.position; expect(va.getAttribute(0).index).toEqual(0); expect(va.getAttribute(0).componentDatatype).toEqual(position.componentDatatype); expect(va.getAttribute(0).componentsPerAttribute).toEqual(position.componentsPerAttribute); expect(va.getAttribute(0).offsetInBytes).toEqual(0); expect(va.getAttribute(0).strideInBytes).toEqual(0); // Tightly packed - var normal = mesh.attributes.position; + var normal = geometry.attributes.position; expect(va.getAttribute(1).index).toEqual(1); expect(va.getAttribute(1).componentDatatype).toEqual(normal.componentDatatype); expect(va.getAttribute(1).componentsPerAttribute).toEqual(normal.componentsPerAttribute); @@ -159,7 +159,7 @@ defineSuite([ }); it('creates a homogeneous multiple-attribute vertex (interleaved)', function() { - var mesh = new Geometry({ + var geometry = new Geometry({ attributes : { position : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, @@ -175,16 +175,16 @@ defineSuite([ }); var va = context.createVertexArrayFromGeometry({ - mesh : mesh, - attributeIndices : GeometryFilters.createAttributeIndices(mesh), + geometry : geometry, + attributeIndices : GeometryFilters.createAttributeIndices(geometry), vertexLayout : VertexLayout.INTERLEAVED }); expect(va.getNumberOfAttributes()).toEqual(2); expect(va.getIndexBuffer()).not.toBeDefined(); - var position = mesh.attributes.position; - var normal = mesh.attributes.position; + var position = geometry.attributes.position; + var normal = geometry.attributes.position; var expectedStride = position.componentDatatype.sizeInBytes * position.componentsPerAttribute + normal.componentDatatype.sizeInBytes * normal.componentsPerAttribute; expect(va.getAttribute(0).index).toEqual(0); @@ -203,7 +203,7 @@ defineSuite([ }); it('creates a heterogeneous multiple-attribute vertex (interleaved)', function() { - var mesh = new Geometry({ + var geometry = new Geometry({ attributes : { position : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, @@ -219,16 +219,16 @@ defineSuite([ }); var va = context.createVertexArrayFromGeometry({ - mesh : mesh, - attributeIndices : GeometryFilters.createAttributeIndices(mesh), + geometry : geometry, + attributeIndices : GeometryFilters.createAttributeIndices(geometry), vertexLayout : VertexLayout.INTERLEAVED }); expect(va.getNumberOfAttributes()).toEqual(2); expect(va.getIndexBuffer()).not.toBeDefined(); - var position = mesh.attributes.position; - var colors = mesh.attributes.colors; + var position = geometry.attributes.position; + var colors = geometry.attributes.colors; var expectedStride = position.componentDatatype.sizeInBytes * position.componentsPerAttribute + colors.componentDatatype.sizeInBytes * colors.componentsPerAttribute; expect(va.getAttribute(0).index).toEqual(0); @@ -247,7 +247,7 @@ defineSuite([ }); it('sorts interleaved attributes from large to small components', function() { - var mesh = new Geometry({ + var geometry = new Geometry({ attributes : { bytes : new GeometryAttribute({ componentDatatype : ComponentDatatype.BYTE, @@ -267,9 +267,9 @@ defineSuite([ } }); - var attributeIndices = GeometryFilters.createAttributeIndices(mesh); + var attributeIndices = GeometryFilters.createAttributeIndices(geometry); var va = context.createVertexArrayFromGeometry({ - mesh : mesh, + geometry : geometry, attributeIndices : attributeIndices, vertexLayout : VertexLayout.INTERLEAVED }); @@ -312,7 +312,7 @@ defineSuite([ it('sorts interleaved attributes from large to small components (2)', function() { // TODO: Color should be normalized - var mesh = new Geometry({ + var geometry = new Geometry({ attributes : { color : new GeometryAttribute({ componentDatatype : ComponentDatatype.UNSIGNED_BYTE, @@ -327,9 +327,9 @@ defineSuite([ } }); - var attributeIndices = GeometryFilters.createAttributeIndices(mesh); + var attributeIndices = GeometryFilters.createAttributeIndices(geometry); var va = context.createVertexArrayFromGeometry({ - mesh : mesh, + geometry : geometry, attributeIndices : attributeIndices, vertexLayout : VertexLayout.INTERLEAVED }); @@ -376,7 +376,7 @@ defineSuite([ }); it('sorts interleaved attributes from large to small components (3)', function() { - var mesh = new Geometry({ + var geometry = new Geometry({ attributes : { unsignedByteAttribute : new GeometryAttribute({ componentDatatype : ComponentDatatype.UNSIGNED_BYTE, @@ -401,9 +401,9 @@ defineSuite([ } }); - var attributeIndices = GeometryFilters.createAttributeIndices(mesh); + var attributeIndices = GeometryFilters.createAttributeIndices(geometry); var va = context.createVertexArrayFromGeometry({ - mesh : mesh, + geometry : geometry, attributeIndices : attributeIndices, vertexLayout : VertexLayout.INTERLEAVED }); @@ -444,7 +444,7 @@ defineSuite([ it('creates a custom interleaved vertex', function() { // TODO: Color should be normalized - var mesh = new Geometry({ + var geometry = new Geometry({ attributes : { position : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, @@ -469,9 +469,9 @@ defineSuite([ } }); - var attributeIndices = GeometryFilters.createAttributeIndices(mesh); + var attributeIndices = GeometryFilters.createAttributeIndices(geometry); var va = context.createVertexArrayFromGeometry({ - mesh : mesh, + geometry : geometry, attributeIndices : attributeIndices, vertexLayout : VertexLayout.INTERLEAVED }); @@ -544,24 +544,24 @@ defineSuite([ }); it('creates an index buffer', function() { - var mesh = new Geometry({ + var geometry = new Geometry({ indexList : [0], primitiveType : PrimitiveType.POINTS }); var va = context.createVertexArrayFromGeometry({ - mesh : mesh + geometry : geometry }); expect(va.getNumberOfAttributes()).toEqual(0); expect(va.getIndexBuffer()).toBeDefined(); expect(va.getIndexBuffer().getUsage()).toEqual(BufferUsage.DYNAMIC_DRAW); // Default expect(va.getIndexBuffer().getIndexDatatype()).toEqual(IndexDatatype.UNSIGNED_SHORT); - expect(va.getIndexBuffer().getNumberOfIndices()).toEqual(mesh.indexList.length); + expect(va.getIndexBuffer().getNumberOfIndices()).toEqual(geometry.indexList.length); }); it('throws with different number of interleaved attributes', function() { - var mesh = new Geometry({ + var geometry = new Geometry({ attributes : { position : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, @@ -578,14 +578,14 @@ defineSuite([ expect(function() { return context.createVertexArrayFromGeometry({ - mesh : mesh, + geometry : geometry, vertexLayout : VertexLayout.INTERLEAVED }); }).toThrow(); }); it('throws with duplicate indices', function() { - var mesh = new Geometry({ + var geometry = new Geometry({ attributes : { position : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, @@ -602,7 +602,7 @@ defineSuite([ expect(function() { return context.createVertexArrayFromGeometry({ - mesh : mesh, + geometry : geometry, attributeIndices : { position : 0, normal : 0 diff --git a/Specs/Scene/MultifrustumSpec.js b/Specs/Scene/MultifrustumSpec.js index ee785616b68a..edbb91318dba 100644 --- a/Specs/Scene/MultifrustumSpec.js +++ b/Specs/Scene/MultifrustumSpec.js @@ -210,13 +210,13 @@ defineSuite([ var dimensions = new Cartesian3(500000.0, 500000.0, 500000.0); var maximumCorner = dimensions.multiplyByScalar(0.5); var minimumCorner = maximumCorner.negate(); - var mesh = new BoxGeometry({ + var geometry = new BoxGeometry({ minimumCorner: minimumCorner, maximumCorner: maximumCorner }); - var attributeIndices = GeometryFilters.createAttributeIndices(mesh); + var attributeIndices = GeometryFilters.createAttributeIndices(geometry); this._va = context.createVertexArrayFromGeometry({ - mesh: mesh, + geometry: geometry, attributeIndices: attributeIndices, bufferUsage: BufferUsage.STATIC_DRAW }); From 77d9e2eef8ed20a88ce6b90927389a52863c4e21 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Thu, 6 Jun 2013 09:51:01 -0400 Subject: [PATCH 147/306] More mesh renames --- Source/Core/PolygonPipeline.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/Core/PolygonPipeline.js b/Source/Core/PolygonPipeline.js index b8f17aaaf8c4..1cac23716c27 100644 --- a/Source/Core/PolygonPipeline.js +++ b/Source/Core/PolygonPipeline.js @@ -845,7 +845,7 @@ define([ * * @exception {DeveloperError} ellipsoid is required. */ - scaleToGeodeticHeight : function(mesh, height, ellipsoid) { + scaleToGeodeticHeight : function(geometry, height, ellipsoid) { ellipsoid = defaultValue(ellipsoid, Ellipsoid.WGS84); var n = scaleToGeodeticHeightN; @@ -853,8 +853,8 @@ define([ height = defaultValue(height, 0.0); - if (typeof mesh !== 'undefined' && typeof mesh.attributes !== 'undefined' && typeof mesh.attributes.position !== 'undefined') { - var positions = mesh.attributes.position.values; + if (typeof geometry !== 'undefined' && typeof geometry.attributes !== 'undefined' && typeof geometry.attributes.position !== 'undefined') { + var positions = geometry.attributes.position.values; var length = positions.length; for ( var i = 0; i < length; i += 3) { @@ -873,7 +873,7 @@ define([ } } - return mesh; + return geometry; }, /** From 8d1fb53251c00d1a161c6502262b364b337a8733 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Thu, 6 Jun 2013 11:21:58 -0400 Subject: [PATCH 148/306] Attempt to cleanup cloning geometry --- Apps/CesiumViewer/CesiumViewer.js | 3 --- Source/Core/BoxGeometry.js | 2 +- Source/Core/CircleGeometry.js | 2 +- Source/Core/EllipseGeometry.js | 2 +- Source/Core/EllipsoidGeometry.js | 2 +- Source/Core/ExtentGeometry.js | 2 +- Source/Core/Geometry.js | 2 +- Source/Core/GeometryFilters.js | 2 -- Source/Core/GeometryInstance.js | 4 ++-- Source/Core/PolygonGeometry.js | 2 +- Source/Core/WallGeometry.js | 2 +- 11 files changed, 10 insertions(+), 15 deletions(-) diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index d497e8da0d25..9326e55432b7 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -86,9 +86,6 @@ define([ widget.startup(); widget.fullscreen.viewModel.fullscreenElement = document.body; - // For debug. This kills performance. - widget.scene.getContext().setThrowOnWebGLError(true); - var scene = widget.scene; var ellipsoid = widget.centralBody.getEllipsoid(); diff --git a/Source/Core/BoxGeometry.js b/Source/Core/BoxGeometry.js index 0cfae61808eb..f86be1e2d839 100644 --- a/Source/Core/BoxGeometry.js +++ b/Source/Core/BoxGeometry.js @@ -382,7 +382,7 @@ define([ /** * DOC_TBA */ - BoxGeometry.prototype.clone = Geometry.prototype.clone; + BoxGeometry.prototype.cloneGeometry = Geometry.prototype.cloneGeometry; return BoxGeometry; }); \ No newline at end of file diff --git a/Source/Core/CircleGeometry.js b/Source/Core/CircleGeometry.js index 708e9f214439..d117a9610002 100644 --- a/Source/Core/CircleGeometry.js +++ b/Source/Core/CircleGeometry.js @@ -88,7 +88,7 @@ define([ /** * DOC_TBA */ - CircleGeometry.prototype.clone = Geometry.prototype.clone; + CircleGeometry.prototype.cloneGeometry = Geometry.prototype.cloneGeometry; return CircleGeometry; }); \ No newline at end of file diff --git a/Source/Core/EllipseGeometry.js b/Source/Core/EllipseGeometry.js index f51486f920fb..8c0d31c79d0c 100644 --- a/Source/Core/EllipseGeometry.js +++ b/Source/Core/EllipseGeometry.js @@ -452,7 +452,7 @@ define([ /** * DOC_TBA */ - EllipseGeometry.prototype.clone = Geometry.prototype.clone; + EllipseGeometry.prototype.cloneGeometry = Geometry.prototype.cloneGeometry; return EllipseGeometry; }); \ No newline at end of file diff --git a/Source/Core/EllipsoidGeometry.js b/Source/Core/EllipsoidGeometry.js index ec7e6812d84c..a08180425f3b 100644 --- a/Source/Core/EllipsoidGeometry.js +++ b/Source/Core/EllipsoidGeometry.js @@ -336,7 +336,7 @@ define([ /** * DOC_TBA */ - EllipsoidGeometry.prototype.clone = Geometry.prototype.clone; + EllipsoidGeometry.prototype.cloneGeometry = Geometry.prototype.cloneGeometry; return EllipsoidGeometry; }); \ No newline at end of file diff --git a/Source/Core/ExtentGeometry.js b/Source/Core/ExtentGeometry.js index 191493d61526..0650fdbc6c81 100644 --- a/Source/Core/ExtentGeometry.js +++ b/Source/Core/ExtentGeometry.js @@ -324,7 +324,7 @@ define([ /** * DOC_TBA */ - ExtentGeometry.prototype.clone = Geometry.prototype.clone; + ExtentGeometry.prototype.cloneGeometry = Geometry.prototype.cloneGeometry; return ExtentGeometry; }); diff --git a/Source/Core/Geometry.js b/Source/Core/Geometry.js index 57c718423bab..2c209cdcee4a 100644 --- a/Source/Core/Geometry.js +++ b/Source/Core/Geometry.js @@ -40,7 +40,7 @@ define([ /** * DOC_TBA */ - Geometry.prototype.clone = function(result) { + Geometry.prototype.cloneGeometry = function(result) { if (typeof result === 'undefined') { // TODO: is this always what we want, for say BoxGeometry? result = new Geometry(); diff --git a/Source/Core/GeometryFilters.js b/Source/Core/GeometryFilters.js index 5389f9fbb4dd..8a0193fd6911 100644 --- a/Source/Core/GeometryFilters.js +++ b/Source/Core/GeometryFilters.js @@ -389,7 +389,6 @@ define([ newIndices.push(i2); if (currentIndex + 3 > sixtyFourK) { - // TODO: is this always what we want, for say BoxGeometry? geometries.push(new Geometry({ attributes : newAttributes, indexList : newIndices, @@ -405,7 +404,6 @@ define([ } if (newIndices.length !== 0) { - // TODO: is this always what we want, for say BoxGeometry? geometries.push(new Geometry({ attributes : newAttributes, indexList : newIndices, diff --git a/Source/Core/GeometryInstance.js b/Source/Core/GeometryInstance.js index b300ba78e346..3a16445b7bd6 100644 --- a/Source/Core/GeometryInstance.js +++ b/Source/Core/GeometryInstance.js @@ -57,10 +57,10 @@ define([ result = new GeometryInstance(); } - result.geometry = this.geometry.clone(); + result.geometry = this.geometry.cloneGeometry(); // Looses type info, e.g., BoxGeometry to Geometry. result.modelMatrix = this.modelMatrix.clone(result.modelMatrix); result.color = (typeof this.color !== 'undefined') ? this.color.clone() : undefined; - result.pickData = this.pickData; // Shadow copy + result.pickData = this.pickData; // Shadow copy return result; }; diff --git a/Source/Core/PolygonGeometry.js b/Source/Core/PolygonGeometry.js index 459de8fa5a5b..96438ef3b521 100644 --- a/Source/Core/PolygonGeometry.js +++ b/Source/Core/PolygonGeometry.js @@ -437,7 +437,7 @@ define([ /** * DOC_TBA */ - PolygonGeometry.prototype.clone = Geometry.prototype.clone; + PolygonGeometry.prototype.cloneGeometry = Geometry.prototype.cloneGeometry; return PolygonGeometry; }); diff --git a/Source/Core/WallGeometry.js b/Source/Core/WallGeometry.js index 92874962b2b1..d0628512cd3c 100644 --- a/Source/Core/WallGeometry.js +++ b/Source/Core/WallGeometry.js @@ -304,7 +304,7 @@ define([ /** * DOC_TBA */ - WallGeometry.prototype.clone = Geometry.prototype.clone; + WallGeometry.prototype.cloneGeometry = Geometry.prototype.cloneGeometry; return WallGeometry; }); From 256c70d91b0be70731fe1b865a5486961e7c1c43 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Fri, 7 Jun 2013 11:15:40 -0400 Subject: [PATCH 149/306] Renamed GeometryFilters file to GeometryPipeline --- Source/Core/{GeometryFilters.js => GeometryPipeline.js} | 0 Specs/Core/{GeometryFiltersSpec.js => GeometryPipelineSpec.js} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename Source/Core/{GeometryFilters.js => GeometryPipeline.js} (100%) rename Specs/Core/{GeometryFiltersSpec.js => GeometryPipelineSpec.js} (100%) diff --git a/Source/Core/GeometryFilters.js b/Source/Core/GeometryPipeline.js similarity index 100% rename from Source/Core/GeometryFilters.js rename to Source/Core/GeometryPipeline.js diff --git a/Specs/Core/GeometryFiltersSpec.js b/Specs/Core/GeometryPipelineSpec.js similarity index 100% rename from Specs/Core/GeometryFiltersSpec.js rename to Specs/Core/GeometryPipelineSpec.js From cd91b97b1f4f9bd13c6a2a2752a82314ab4a1b46 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Fri, 7 Jun 2013 13:34:44 -0400 Subject: [PATCH 150/306] Renamed GeometryFilter to GeometryPipeline --- Apps/CesiumViewer/CesiumViewer.js | 4 +- CHANGES.md | 10 +- Source/Core/GeometryPipeline.js | 52 +++---- Source/Core/PolygonGeometry.js | 6 +- Source/Renderer/Context.js | 6 +- Source/Scene/CentralBodySurface.js | 8 +- Source/Scene/Polygon.js | 20 +-- Source/Scene/Primitive.js | 18 +-- Source/Scene/SkyAtmosphere.js | 6 +- Source/Scene/SkyBox.js | 6 +- Specs/Core/GeometryPipelineSpec.js | 184 +++++++++++------------ Specs/Renderer/VertexArrayFactorySpec.js | 22 +-- Specs/Scene/MultifrustumSpec.js | 6 +- 13 files changed, 174 insertions(+), 174 deletions(-) diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index 9326e55432b7..368c9f9aae7f 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -18,7 +18,7 @@ define([ 'Core/EllipsoidGeometry', 'Core/PolygonGeometry', 'Core/BoxGeometry', - 'Core/GeometryFilters', + 'Core/GeometryPipeline', 'Core/VertexFormat', 'Core/Transforms', 'Core/ScreenSpaceEventHandler', @@ -51,7 +51,7 @@ define([ EllipsoidGeometry, PolygonGeometry, BoxGeometry, - GeometryFilters, + GeometryPipeline, VertexFormat, Transforms, ScreenSpaceEventHandler, diff --git a/CHANGES.md b/CHANGES.md index ce5995ea83f4..4c392c5aa46f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -17,8 +17,8 @@ Beta Releases * Replaced `BoxTessellator` with `BoxGeometry`. * Replaced `ExtentTessletaor` with `ExtentGeometry`. * Removed `PlaneTessellator`. It was incomplete and not used. - * Renamed `MeshFilters` to `GeometryFilters`. - * Renamed `MeshFilters.toWireframeInPlace` to `GeometryFilters.toWireframe`. + * Renamed `MeshFilters` to `GeometryPipeline`. + * Renamed `MeshFilters.toWireframeInPlace` to `GeometryPipeline.toWireframe`. * Renamed `Context.createVertexArrayFromMesh` to `Context.createVertexArrayFromGeometry`. Likewise, renamed `mesh` constructor property to `geometry`. * Renamed `ComponentDatatype.*.toTypedArray` to `ComponentDatatype.*.createTypedArray`. * Replaced `Uniform.getFrameNumber` and `Uniform.getTime` with `Uniform.getFrameState`, which returns the full frame state. @@ -26,9 +26,9 @@ Beta Releases * Added `height` parameter to `BoundingSphere.fromExtent3D`. * Added `height` parameter to `Extent.subsample`. * Improved the performance of drawing polygons created with `configureFromPolygonHierarchy`. -* Added `GeometryFilters.combine` to combine meshes for better batching. -* Added `GeometryFilters.computeNormal` to find the normals of vertices in a mesh. -* Added `GeometryFilters.computeTangentAndBinormal` to find the tangent and binormal vectors of vertices in a mesh. +* Added `GeometryPipeline.combine` to combine meshes for better batching. +* Added `GeometryPipeline.computeNormal` to find the normals of vertices in a mesh. +* Added `GeometryPipeline.computeTangentAndBinormal` to find the tangent and binormal vectors of vertices in a mesh. * Added `BoundingSphere.fromEllipsoid`. * Added renderer support for `OES_element_index_uint`, which can improve performance by reducing batch sizes. * Added `czm_tangentToEyeSpaceMatrix` built-in GLSL function. diff --git a/Source/Core/GeometryPipeline.js b/Source/Core/GeometryPipeline.js index 8a0193fd6911..a634ba29a864 100644 --- a/Source/Core/GeometryPipeline.js +++ b/Source/Core/GeometryPipeline.js @@ -34,11 +34,11 @@ define([ /** * DOC_TBA * - * @exports GeometryFilters + * @exports GeometryPipeline * * @see Context#createVertexArrayFromGeometry */ - var GeometryFilters = {}; + var GeometryPipeline = {}; /** * Converts a geometry's triangle indices to line indices. The geometry's indexList with @@ -55,9 +55,9 @@ define([ * * @example * var geometry = new BoxGeometry(); - * geometry = GeometryFilters.toWireframe(geometry); + * geometry = GeometryPipeline.toWireframe(geometry); */ - GeometryFilters.toWireframe = function(geometry) { + GeometryPipeline.toWireframe = function(geometry) { function addTriangle(lines, i0, i1, i2) { lines.push(i0); lines.push(i1); @@ -133,7 +133,7 @@ define([ /** * DOC_TBA */ - GeometryFilters.createAttributeIndices = function(geometry) { + GeometryPipeline.createAttributeIndices = function(geometry) { var indices = {}; if (typeof geometry !== 'undefined') { @@ -153,7 +153,7 @@ define([ /** * DOC_TBA */ - GeometryFilters.mapAttributeIndices = function(indices, map) { + GeometryPipeline.mapAttributeIndices = function(indices, map) { var mappedIndices = {}; if (typeof indices !== 'undefined' && typeof map !== 'undefined') { @@ -180,13 +180,13 @@ define([ * * @returns The modified geometry argument, with its vertices and indices reordered for the GPU's pre-vertex-shader cache. * - * @see GeometryFilters.reorderForPostVertexCache + * @see GeometryPipeline.reorderForPostVertexCache * * @example * var geometry = new EllipsoidGeometry(...); - * geometry = GeometryFilters.reorderForPreVertexCache(geometry); + * geometry = GeometryPipeline.reorderForPreVertexCache(geometry); */ - GeometryFilters.reorderForPreVertexCache = function(geometry) { + GeometryPipeline.reorderForPreVertexCache = function(geometry) { if (typeof geometry !== 'undefined') { var numVertices = Geometry.computeNumberOfVertices(geometry); @@ -264,7 +264,7 @@ define([ * * @returns The modified geometry argument, with its indices optimally reordered for the post-vertex-shader cache. * - * @see GeometryFilters.reorderForPreVertexCache + * @see GeometryPipeline.reorderForPreVertexCache * @see Tipsify * @see * Fast Triangle Reordering for Vertex Locality and Reduced Overdraw @@ -272,9 +272,9 @@ define([ * * @example * var geometry = new EllipsoidGeometry(...); - * geometry = GeometryFilters.reorderForPostVertexCache(geometry); + * geometry = GeometryPipeline.reorderForPostVertexCache(geometry); */ - GeometryFilters.reorderForPostVertexCache = function(geometry, cacheCapacity) { + GeometryPipeline.reorderForPostVertexCache = function(geometry, cacheCapacity) { if (typeof geometry !== 'undefined') { var indices = geometry.indexList; if (typeof indices !== 'undefined') { @@ -295,7 +295,7 @@ define([ return geometry; }; - GeometryFilters._copyAttributesDescriptions = function(attributes) { + GeometryPipeline._copyAttributesDescriptions = function(attributes) { var newAttributes = {}; for ( var attribute in attributes) { @@ -331,7 +331,7 @@ define([ * @exception {DeveloperError} geometry.primitiveType must equal to PrimitiveType.TRIANGLES. * @exception {DeveloperError} All geometry attribute lists must have the same number of attributes. */ - GeometryFilters.fitToUnsignedShortIndices = function(geometry) { + GeometryPipeline.fitToUnsignedShortIndices = function(geometry) { var geometries = []; if (typeof geometry !== 'undefined') { @@ -348,7 +348,7 @@ define([ var oldToNewIndex = []; var newIndices = []; var currentIndex = 0; - var newAttributes = GeometryFilters._copyAttributesDescriptions(geometry.attributes); + var newAttributes = GeometryPipeline._copyAttributesDescriptions(geometry.attributes); var originalIndices = geometry.indexList; var numberOfIndices = originalIndices.length; @@ -399,7 +399,7 @@ define([ oldToNewIndex = []; newIndices = []; currentIndex = 0; - newAttributes = GeometryFilters._copyAttributesDescriptions(geometry.attributes); + newAttributes = GeometryPipeline._copyAttributesDescriptions(geometry.attributes); } } @@ -422,7 +422,7 @@ define([ /** * DOC_TBA */ - GeometryFilters.projectTo2D = function(geometry, projection) { + GeometryPipeline.projectTo2D = function(geometry, projection) { if (typeof geometry !== 'undefined' && typeof geometry.attributes.position !== 'undefined') { projection = typeof projection !== 'undefined' ? projection : new GeographicProjection(); var ellipsoid = projection.getEllipsoid(); @@ -476,11 +476,11 @@ define([ * @exception {DeveloperError} The attribute componentDatatype must be ComponentDatatype.FLOAT. * * @example - * geometry = GeometryFilters.encodeAttribute(geometry, 'position3D', 'position3DHigh', 'position3DLow'); + * geometry = GeometryPipeline.encodeAttribute(geometry, 'position3D', 'position3DHigh', 'position3DLow'); * * @see EncodedCartesian3 */ - GeometryFilters.encodeAttribute = function(geometry, attributeName, attributeHighName, attributeLowName) { + GeometryPipeline.encodeAttribute = function(geometry, attributeName, attributeHighName, attributeLowName) { attributeName = defaultValue(attributeName, 'position'); attributeHighName = defaultValue(attributeHighName, 'positionHigh'); attributeLowName = defaultValue(attributeLowName, 'positionLow'); @@ -560,7 +560,7 @@ define([ * * @exception {DeveloperError} instance is required. */ - GeometryFilters.transformToWorldCoordinates = function(instance) { + GeometryPipeline.transformToWorldCoordinates = function(instance) { if (typeof instance === 'undefined') { throw new DeveloperError('instance is required.'); } @@ -655,7 +655,7 @@ define([ * @exception {DeveloperError} instances is required and must have length greater than zero. * @exception {DeveloperError} All instances must have the same modelMatrix. */ - GeometryFilters.combine = function(instances) { + GeometryPipeline.combine = function(instances) { if ((typeof instances === 'undefined') || (instances.length < 1)) { throw new DeveloperError('instances is required and must have length greater than zero.'); } @@ -813,10 +813,10 @@ define([ * @exception {DeveloperError} geometry.attributes.position.values.length must be a multiple of 3 * * @example - * geometry = GeometryFilters.computeNormal(geometry); + * geometry = GeometryPipeline.computeNormal(geometry); * */ - GeometryFilters.computeNormal = function(geometry) { + GeometryPipeline.computeNormal = function(geometry) { if (typeof geometry === 'undefined') { throw new DeveloperError('geometry is required.'); } @@ -963,9 +963,9 @@ define([ * @exception {DeveloperError} geometry.attributes.st.values.length must be a multiple of 2 * * @example - * geometry = GeometryFilters.computeTangentAndBinormal(geometry); + * geometry = GeometryPipeline.computeTangentAndBinormal(geometry); */ - GeometryFilters.computeTangentAndBinormal = function(geometry) { + GeometryPipeline.computeTangentAndBinormal = function(geometry) { if (typeof geometry === 'undefined') { throw new DeveloperError('geometry is required.'); } @@ -1092,5 +1092,5 @@ define([ return geometry; }; - return GeometryFilters; + return GeometryPipeline; }); diff --git a/Source/Core/PolygonGeometry.js b/Source/Core/PolygonGeometry.js index 96438ef3b521..d5b82aaba841 100644 --- a/Source/Core/PolygonGeometry.js +++ b/Source/Core/PolygonGeometry.js @@ -13,7 +13,7 @@ define([ './Geometry', './GeometryAttribute', './GeometryInstance', - './GeometryFilters', + './GeometryPipeline', './Intersect', './Math', './Matrix3', @@ -36,7 +36,7 @@ define([ Geometry, GeometryAttribute, GeometryInstance, - GeometryFilters, + GeometryPipeline, Intersect, CesiumMath, Matrix3, @@ -281,7 +281,7 @@ define([ throw new DeveloperError('positions or hierarchy must be supplied.'); } - geometry = GeometryFilters.combine(geometries); + geometry = GeometryPipeline.combine(geometries); geometry = PolygonPipeline.scaleToGeodeticHeight(geometry, height, ellipsoid); var attributes = {}; diff --git a/Source/Renderer/Context.js b/Source/Renderer/Context.js index 011a2fcfa749..89317501717c 100644 --- a/Source/Renderer/Context.js +++ b/Source/Renderer/Context.js @@ -2313,7 +2313,7 @@ define([ * @see Context#createVertexArray * @see Context#createVertexBuffer * @see Context#createIndexBuffer - * @see GeometryFilters.createAttributeIndices + * @see GeometryPipeline.createAttributeIndices * @see ShaderProgram * * @example @@ -2323,7 +2323,7 @@ define([ * var geometry = new BoxGeometry(); * var va = context.createVertexArrayFromGeometry({ * geometry : geometry, - * attributeIndices : GeometryFilters.createAttributeIndices(geometry), + * attributeIndices : GeometryPipeline.createAttributeIndices(geometry), * }); * * //////////////////////////////////////////////////////////////////////////////// @@ -2332,7 +2332,7 @@ define([ * // single vertex buffer. The vertex and index buffer have static draw usage. * var va = context.createVertexArrayFromGeometry({ * geometry : geometry, - * attributeIndices : GeometryFilters.createAttributeIndices(geometry), + * attributeIndices : GeometryPipeline.createAttributeIndices(geometry), * bufferUsage : BufferUsage.STATIC_DRAW, * vertexLayout : VertexLayout.INTERLEAVED * }); diff --git a/Source/Scene/CentralBodySurface.js b/Source/Scene/CentralBodySurface.js index 21cdcb617a5d..5d4ada3deb29 100644 --- a/Source/Scene/CentralBodySurface.js +++ b/Source/Scene/CentralBodySurface.js @@ -12,7 +12,7 @@ define([ '../Core/EllipsoidalOccluder', '../Core/Intersect', '../Core/Matrix4', - '../Core/GeometryFilters', + '../Core/GeometryPipeline', '../Core/PrimitiveType', '../Core/Queue', '../Core/WebMercatorProjection', @@ -36,7 +36,7 @@ define([ EllipsoidalOccluder, Intersect, Matrix4, - GeometryFilters, + GeometryPipeline, PrimitiveType, Queue, WebMercatorProjection, @@ -700,10 +700,10 @@ define([ ellipsoid : new Ellipsoid(radius, radius, radius), numberOfPartitions : 10 }); - GeometryFilters.toWireframe(sphere); + GeometryPipeline.toWireframe(sphere); surface._debug.boundingSphereVA = context.createVertexArrayFromGeometry({ geometry : sphere, - attributeIndices : GeometryFilters.createAttributeIndices(sphere) + attributeIndices : GeometryPipeline.createAttributeIndices(sphere) }); } diff --git a/Source/Scene/Polygon.js b/Source/Scene/Polygon.js index a14ad5d1fbd5..a3aa93faa8f8 100644 --- a/Source/Scene/Polygon.js +++ b/Source/Scene/Polygon.js @@ -13,7 +13,7 @@ define([ '../Core/Cartesian3', '../Core/Cartesian4', '../Core/ComponentDatatype', - '../Core/GeometryFilters', + '../Core/GeometryPipeline', '../Core/GeometryInstance', '../Core/PrimitiveType', '../Core/EllipsoidTangentPlane', @@ -48,7 +48,7 @@ define([ Cartesian3, Cartesian4, ComponentDatatype, - GeometryFilters, + GeometryPipeline, GeometryInstance, PrimitiveType, EllipsoidTangentPlane, @@ -556,10 +556,10 @@ define([ return undefined; } - geometry = GeometryFilters.combine(geometries); + geometry = GeometryPipeline.combine(geometries); geometry = PolygonPipeline.scaleToGeodeticHeight(geometry, polygon.height, polygon.ellipsoid); - geometry = GeometryFilters.reorderForPostVertexCache(geometry); - geometry = GeometryFilters.reorderForPreVertexCache(geometry); + geometry = GeometryPipeline.reorderForPostVertexCache(geometry); + geometry = GeometryPipeline.reorderForPreVertexCache(geometry); if (polygon._mode === SceneMode.SCENE3D) { geometry.attributes.position2DHigh = { // Not actually used in shader @@ -568,9 +568,9 @@ define([ geometry.attributes.position2DLow = { // Not actually used in shader value : [0.0, 0.0] }; - geometry = GeometryFilters.encodeAttribute(geometry, 'position', 'position3DHigh', 'position3DLow'); + geometry = GeometryPipeline.encodeAttribute(geometry, 'position', 'position3DHigh', 'position3DLow'); } else { - geometry = GeometryFilters.projectTo2D(geometry, polygon._projection); + geometry = GeometryPipeline.projectTo2D(geometry, polygon._projection); if (polygon._mode !== SceneMode.SCENE3D) { var projectedPositions = geometry.attributes.position2D.values; @@ -585,11 +585,11 @@ define([ polygon._boundingVolume2D.center = new Cartesian3(0.0, center2DPositions.x, center2DPositions.y); } - geometry = GeometryFilters.encodeAttribute(geometry, 'position3D', 'position3DHigh', 'position3DLow'); - geometry = GeometryFilters.encodeAttribute(geometry, 'position2D', 'position2DHigh', 'position2DLow'); + geometry = GeometryPipeline.encodeAttribute(geometry, 'position3D', 'position3DHigh', 'position3DLow'); + geometry = GeometryPipeline.encodeAttribute(geometry, 'position2D', 'position2DHigh', 'position2DLow'); } - return GeometryFilters.fitToUnsignedShortIndices(geometry); + return GeometryPipeline.fitToUnsignedShortIndices(geometry); } function getGranularity(polygon, mode) { diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index d86bfe0cc31b..6849a3583498 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -5,7 +5,7 @@ define([ '../Core/destroyObject', '../Core/Matrix4', '../Core/Color', - '../Core/GeometryFilters', + '../Core/GeometryPipeline', '../Core/PrimitiveType', '../Core/BoundingSphere', '../Core/Geometry', @@ -23,7 +23,7 @@ define([ destroyObject, Matrix4, Color, - GeometryFilters, + GeometryPipeline, PrimitiveType, BoundingSphere, Geometry, @@ -276,7 +276,7 @@ define([ if (toWorld) { for (i = 0; i < length; ++i) { - GeometryFilters.transformToWorldCoordinates(instances[i]); + GeometryPipeline.transformToWorldCoordinates(instances[i]); } } else { // Leave geometry in local coordinate system; auto update model-matrix. @@ -311,14 +311,14 @@ define([ transformToWorldCoordinates(primitive, insts); // Combine into single geometry for better rendering performance. - var geometry = GeometryFilters.combine(insts); + var geometry = GeometryPipeline.combine(insts); // Split position for GPU RTE - GeometryFilters.encodeAttribute(geometry, 'position', 'positionHigh', 'positionLow'); + GeometryPipeline.encodeAttribute(geometry, 'position', 'positionHigh', 'positionLow'); if (!context.getElementIndexUint()) { // Break into multiple geometries to fit within unsigned short indices if needed - return GeometryFilters.fitToUnsignedShortIndices(geometry); + return GeometryPipeline.fitToUnsignedShortIndices(geometry); } // Unsigned int indices are supported. No need to break into multiple geometries. @@ -350,12 +350,12 @@ define([ if (this._vertexCacheOptimize) { // Optimize for vertex shader caches for (i = 0; i < length; ++i) { - GeometryFilters.reorderForPostVertexCache(geometries[i]); - GeometryFilters.reorderForPreVertexCache(geometries[i]); + GeometryPipeline.reorderForPostVertexCache(geometries[i]); + GeometryPipeline.reorderForPreVertexCache(geometries[i]); } } - var attributeIndices = GeometryFilters.createAttributeIndices(geometries[0]); + var attributeIndices = GeometryPipeline.createAttributeIndices(geometries[0]); var va = []; for (i = 0; i < length; ++i) { diff --git a/Source/Scene/SkyAtmosphere.js b/Source/Scene/SkyAtmosphere.js index 03cc32e4470d..13a029250f9c 100644 --- a/Source/Scene/SkyAtmosphere.js +++ b/Source/Scene/SkyAtmosphere.js @@ -3,7 +3,7 @@ define([ '../Core/defaultValue', '../Core/EllipsoidGeometry', '../Core/destroyObject', - '../Core/GeometryFilters', + '../Core/GeometryPipeline', '../Core/PrimitiveType', '../Core/Ellipsoid', '../Renderer/BufferUsage', @@ -17,7 +17,7 @@ define([ defaultValue, EllipsoidGeometry, destroyObject, - GeometryFilters, + GeometryPipeline, PrimitiveType, Ellipsoid, BufferUsage, @@ -139,7 +139,7 @@ define([ }); command.vertexArray = context.createVertexArrayFromGeometry({ geometry : geometry, - attributeIndices : GeometryFilters.createAttributeIndices(geometry), + attributeIndices : GeometryPipeline.createAttributeIndices(geometry), bufferUsage : BufferUsage.STATIC_DRAW }); command.primitiveType = PrimitiveType.TRIANGLES; diff --git a/Source/Scene/SkyBox.js b/Source/Scene/SkyBox.js index 421b4aa9072d..d9d3198e1b9c 100644 --- a/Source/Scene/SkyBox.js +++ b/Source/Scene/SkyBox.js @@ -5,7 +5,7 @@ define([ '../Core/destroyObject', '../Core/DeveloperError', '../Core/Matrix4', - '../Core/GeometryFilters', + '../Core/GeometryPipeline', '../Core/VertexFormat', '../Core/PrimitiveType', '../Renderer/loadCubeMap', @@ -21,7 +21,7 @@ define([ destroyObject, DeveloperError, Matrix4, - GeometryFilters, + GeometryPipeline, VertexFormat, PrimitiveType, loadCubeMap, @@ -154,7 +154,7 @@ define([ dimensions : new Cartesian3(2.0, 2.0, 2.0), vertexFormat : VertexFormat.POSITION_ONLY }); - var attributeIndices = GeometryFilters.createAttributeIndices(geometry); + var attributeIndices = GeometryPipeline.createAttributeIndices(geometry); command.primitiveType = PrimitiveType.TRIANGLES; command.modelMatrix = Matrix4.IDENTITY.clone(); diff --git a/Specs/Core/GeometryPipelineSpec.js b/Specs/Core/GeometryPipelineSpec.js index ac10d19d74e3..1f550219b1f0 100644 --- a/Specs/Core/GeometryPipelineSpec.js +++ b/Specs/Core/GeometryPipelineSpec.js @@ -1,6 +1,6 @@ /*global defineSuite*/ defineSuite([ - 'Core/GeometryFilters', + 'Core/GeometryPipeline', 'Core/PrimitiveType', 'Core/ComponentDatatype', 'Core/EllipsoidGeometry', @@ -15,7 +15,7 @@ defineSuite([ 'Core/VertexFormat', 'Core/Math' ], function( - GeometryFilters, + GeometryPipeline, PrimitiveType, ComponentDatatype, EllipsoidGeometry, @@ -33,7 +33,7 @@ defineSuite([ /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/ it('converts triangles to wireframe in place', function() { - var geometry = GeometryFilters.toWireframe(new Geometry({ + var geometry = GeometryPipeline.toWireframe(new Geometry({ indexList : [0, 1, 2, 3, 4, 5], primitiveType : PrimitiveType.TRIANGLES })); @@ -59,7 +59,7 @@ defineSuite([ }); it('converts a triangle fan to wireframe in place', function() { - var geometry = GeometryFilters.toWireframe(new Geometry({ + var geometry = GeometryPipeline.toWireframe(new Geometry({ indexList : [0, 1, 2, 3], primitiveType : PrimitiveType.TRIANGLE_FAN })); @@ -85,7 +85,7 @@ defineSuite([ }); it('converts a triangle strip to wireframe in place', function() { - var geometry = GeometryFilters.toWireframe(new Geometry({ + var geometry = GeometryPipeline.toWireframe(new Geometry({ indexList : [0, 1, 2, 3], primitiveType : PrimitiveType.TRIANGLE_STRIP })); @@ -119,7 +119,7 @@ defineSuite([ } }); - var indices = GeometryFilters.createAttributeIndices(geometry); + var indices = GeometryPipeline.createAttributeIndices(geometry); var validIndices = [0, 1, 2]; expect(validIndices).toContain(indices.position); @@ -136,7 +136,7 @@ defineSuite([ colors : 2 }; - var mappedIndices = GeometryFilters.mapAttributeIndices(indices, { + var mappedIndices = GeometryPipeline.mapAttributeIndices(indices, { positions : 'position', normals : 'normal', colors : 'color' @@ -164,7 +164,7 @@ defineSuite([ } }); - geometry = GeometryFilters.reorderForPreVertexCache(geometry); + geometry = GeometryPipeline.reorderForPreVertexCache(geometry); }).toThrow(); }); @@ -186,7 +186,7 @@ defineSuite([ primitiveType : PrimitiveType.TRIANGLES }); - GeometryFilters.reorderForPreVertexCache(geometry); + GeometryPipeline.reorderForPreVertexCache(geometry); expect(geometry.indexList[0]).toEqual(0); expect(geometry.indexList[1]).toEqual(1); @@ -245,7 +245,7 @@ defineSuite([ maximumIndex : maximumIndex, cacheSize : 24}); expect(ACMRbefore).toBeGreaterThan(1.00); - geometry = GeometryFilters.reorderForPostVertexCache(geometry); + geometry = GeometryPipeline.reorderForPostVertexCache(geometry); indices = geometry.indexList; var ACMRafter = Tipsify.calculateACMR({indices : indices, maximumIndex : maximumIndex, @@ -271,7 +271,7 @@ defineSuite([ primitiveType : PrimitiveType.TRIANGLES }); - var geometries = GeometryFilters.fitToUnsignedShortIndices(geometry); + var geometries = GeometryPipeline.fitToUnsignedShortIndices(geometry); expect(geometries.length).toEqual(1); expect(geometries[0]).toBe(geometry); @@ -296,7 +296,7 @@ defineSuite([ primitiveType : PrimitiveType.TRIANGLES }); - var geometries = GeometryFilters.fitToUnsignedShortIndices(geometry); + var geometries = GeometryPipeline.fitToUnsignedShortIndices(geometry); expect(geometries.length).toEqual(1); expect(geometries[0].attributes.time.componentDatatype).toEqual(ComponentDatatype.FLOAT); @@ -333,7 +333,7 @@ defineSuite([ primitiveType : PrimitiveType.TRIANGLES }); - var geometries = GeometryFilters.fitToUnsignedShortIndices(geometry); + var geometries = GeometryPipeline.fitToUnsignedShortIndices(geometry); expect(geometries.length).toEqual(2); @@ -358,7 +358,7 @@ defineSuite([ }); expect(function() { - return GeometryFilters.fitToUnsignedShortIndices(geometry); + return GeometryPipeline.fitToUnsignedShortIndices(geometry); }).toThrow(); }); @@ -381,7 +381,7 @@ defineSuite([ }); expect(function() { - return GeometryFilters.fitToUnsignedShortIndices(geometry); + return GeometryPipeline.fitToUnsignedShortIndices(geometry); }).toThrow(); }); @@ -397,7 +397,7 @@ defineSuite([ values : [p1.x, p1.y, p1.z, p2.x, p2.y, p2.z] }; - geometry = GeometryFilters.projectTo2D(geometry); + geometry = GeometryPipeline.projectTo2D(geometry); var ellipsoid = Ellipsoid.WGS84; var projection = new GeographicProjection(); @@ -417,7 +417,7 @@ defineSuite([ expect(geometry.attributes.position3D.values[5]).toEqual(p2.z); }); - it('GeometryFilters.encodeAttribute encodes positions', function() { + it('GeometryPipeline.encodeAttribute encodes positions', function() { var c = new Cartesian3(-10000000.0, 0.0, 10000000.0); var encoded = EncodedCartesian3.fromCartesian(c); @@ -430,7 +430,7 @@ defineSuite([ }) } }); - geometry = GeometryFilters.encodeAttribute(geometry); + geometry = GeometryPipeline.encodeAttribute(geometry); expect(geometry.attributes.positionHigh).toBeDefined(); expect(geometry.attributes.positionHigh.values[0]).toEqual(encoded.high.x); @@ -443,25 +443,25 @@ defineSuite([ expect(geometry.attributes.position).not.toBeDefined(); }); - it('GeometryFilters.encodeAttribute throws without a geometry', function() { + it('GeometryPipeline.encodeAttribute throws without a geometry', function() { expect(function() { - GeometryFilters.encodeAttribute(undefined); + GeometryPipeline.encodeAttribute(undefined); }).toThrow(); }); - it('GeometryFilters.encodeAttribute throws with geometry without attributes property', function() { + it('GeometryPipeline.encodeAttribute throws with geometry without attributes property', function() { expect(function() { - GeometryFilters.encodeAttribute({}); + GeometryPipeline.encodeAttribute({}); }).toThrow(); }); - it('GeometryFilters.encodeAttribute throws without attribute', function() { + it('GeometryPipeline.encodeAttribute throws without attribute', function() { expect(function() { - GeometryFilters.encodeAttribute(new Geometry()); + GeometryPipeline.encodeAttribute(new Geometry()); }).toThrow(); }); - it('GeometryFilters.encodeAttribute throws without ComponentDatatype.FLOAT', function() { + it('GeometryPipeline.encodeAttribute throws without ComponentDatatype.FLOAT', function() { expect(function() { var geometry = new Geometry({ attributes : new GeometryAttribute({ @@ -470,11 +470,11 @@ defineSuite([ values : [0.0] }) }); - GeometryFilters.encodeAttribute(geometry); + GeometryPipeline.encodeAttribute(geometry); }).toThrow(); }); - it('GeometryFilters.combine combines one geometry', function() { + it('GeometryPipeline.combine combines one geometry', function() { var instance = new GeometryInstance({ geometry : new Geometry({ attributes : new GeometryAttribute({ @@ -487,11 +487,11 @@ defineSuite([ }), }); - var combined = GeometryFilters.combine([instance]); + var combined = GeometryPipeline.combine([instance]); expect(combined).toBe(instance.geometry); }); - it('GeometryFilters.combine combines several geometries', function() { + it('GeometryPipeline.combine combines several geometries', function() { var instance = new GeometryInstance({ geometry : new Geometry({ attributes : { @@ -536,7 +536,7 @@ defineSuite([ }) }); - var combined = GeometryFilters.combine([instance, anotherInstance]); + var combined = GeometryPipeline.combine([instance, anotherInstance]); expect(combined).toEqual(new Geometry({ attributes : { position : new GeometryAttribute({ @@ -557,33 +557,33 @@ defineSuite([ })); }); - it('GeometryFilters.combine throws with instances', function() { + it('GeometryPipeline.combine throws with instances', function() { expect(function() { - GeometryFilters.combine(); + GeometryPipeline.combine(); }).toThrow(); }); - it('GeometryFilters.combine throws when instances.length is zero', function() { + it('GeometryPipeline.combine throws when instances.length is zero', function() { expect(function() { - GeometryFilters.combine([]); + GeometryPipeline.combine([]); }).toThrow(); }); - it('GeometryFilters.computeNormal throws when geometry is undefined', function() { + it('GeometryPipeline.computeNormal throws when geometry is undefined', function() { expect(function() { - GeometryFilters.computeNormal(); + GeometryPipeline.computeNormal(); }).toThrow(); }); - it('GeometryFilters.computeNormal throws when geometry.attributes.position is undefined', function() { + it('GeometryPipeline.computeNormal throws when geometry.attributes.position is undefined', function() { expect(function() { - GeometryFilters.computeNormal(new Geometry()); + GeometryPipeline.computeNormal(new Geometry()); }).toThrow(); }); - it('GeometryFilters.computeNormal throws when geometry.attributes.position.values is undefined', function() { + it('GeometryPipeline.computeNormal throws when geometry.attributes.position.values is undefined', function() { expect(function() { - GeometryFilters.computeNormal(new Geometry({ + GeometryPipeline.computeNormal(new Geometry({ attributes: { position: new GeometryAttribute() } @@ -591,9 +591,9 @@ defineSuite([ }).toThrow(); }); - it('GeometryFilters.computeNormal throws when geometry.attributes.position.componentsPerAttribute is not 3', function() { + it('GeometryPipeline.computeNormal throws when geometry.attributes.position.componentsPerAttribute is not 3', function() { expect(function() { - GeometryFilters.computeNormal(new Geometry({ + GeometryPipeline.computeNormal(new Geometry({ attributes: { position: new GeometryAttribute({ values : [3, 2, 1, 1, 2, 4], @@ -604,9 +604,9 @@ defineSuite([ }).toThrow(); }); - it('GeometryFilters.computeNormal throws when geometry.attributes.position.values is not a multiple of 3', function() { + it('GeometryPipeline.computeNormal throws when geometry.attributes.position.values is not a multiple of 3', function() { expect(function() { - GeometryFilters.computeNormal(new Geometry( { + GeometryPipeline.computeNormal(new Geometry( { attributes: { position: new GeometryAttribute({ values: [3, 2, 1, 1, 2, 4, 3], @@ -617,7 +617,7 @@ defineSuite([ }).toThrow(); }); - it('GeometryFilters.computeNormal does not compute normals when geometry.indexList is undefined', function() { + it('GeometryPipeline.computeNormal does not compute normals when geometry.indexList is undefined', function() { var geometry = new Geometry({ attributes: { position: new GeometryAttribute({ @@ -627,12 +627,12 @@ defineSuite([ } }); - geometry = GeometryFilters.computeNormal(geometry); + geometry = GeometryPipeline.computeNormal(geometry); expect(typeof geometry.attributes.normal === 'undefined').toEqual(true); }); - it('GeometryFilters.computeNormal does not compute normals when primitive type is not triangle', function() { + it('GeometryPipeline.computeNormal does not compute normals when primitive type is not triangle', function() { var geometry = new Geometry({ attributes: { position: new GeometryAttribute({ @@ -644,13 +644,13 @@ defineSuite([ primitiveType: PrimitiveType.TRIANGLE_STRIP }); - geometry = GeometryFilters.computeNormal(geometry); + geometry = GeometryPipeline.computeNormal(geometry); expect(typeof geometry.attributes.normal === 'undefined').toEqual(true); }); - it('GeometryFilters.computeNormal computes normal for one triangle', function() { + it('GeometryPipeline.computeNormal computes normal for one triangle', function() { var geometry = new Geometry({ attributes: { position: new GeometryAttribute({ @@ -662,13 +662,13 @@ defineSuite([ primitiveType: PrimitiveType.TRIANGLES }); - geometry = GeometryFilters.computeNormal(geometry); + geometry = GeometryPipeline.computeNormal(geometry); expect(geometry.attributes.normal.values.length).toEqual(3*3); expect(geometry.attributes.normal.values).toEqual([0, 0, 1, 0, 0, 1, 0, 0, 1]); }); - it('GeometryFilters.computeNormal computes normal for two triangles', function() { + it('GeometryPipeline.computeNormal computes normal for two triangles', function() { var geometry = new Geometry({ attributes: { position: new GeometryAttribute({ @@ -680,7 +680,7 @@ defineSuite([ primitiveType: PrimitiveType.TRIANGLES }); - geometry = GeometryFilters.computeNormal(geometry); + geometry = GeometryPipeline.computeNormal(geometry); expect(geometry.attributes.normal.values.length).toEqual(4*3); var a = new Cartesian3(-1, 0, 1).normalize(); @@ -690,7 +690,7 @@ defineSuite([ expect(geometry.attributes.normal.values.slice(9, 12)).toEqual([a.x, a.y, a.z]); }); - it('GeometryFilters.computeNormal computes normal for six triangles', function() { + it('GeometryPipeline.computeNormal computes normal for six triangles', function() { var geometry = new Geometry ({ attributes: { position: new GeometryAttribute({ @@ -702,7 +702,7 @@ defineSuite([ primitiveType: PrimitiveType.TRIANGLES }); - geometry = GeometryFilters.computeNormal(geometry); + geometry = GeometryPipeline.computeNormal(geometry); expect(geometry.attributes.normal.values.length).toEqual(7*3); var a = new Cartesian3(-1, -1, -1).normalize(); @@ -718,23 +718,23 @@ defineSuite([ expect(geometry.attributes.normal.values.slice(18,21)).toEqual([0, 0, -1]); }); - it('GeometryFilters.computeTangentAndBinormal throws when geometry is undefined', function() { + it('GeometryPipeline.computeTangentAndBinormal throws when geometry is undefined', function() { expect(function() { - GeometryFilters.computeTangentAndBinormal(); + GeometryPipeline.computeTangentAndBinormal(); }).toThrow(); }); - it('GeometryFilters.computeTangentAndBinormal throws when geometry.attributes.position is undefined', function() { + it('GeometryPipeline.computeTangentAndBinormal throws when geometry.attributes.position is undefined', function() { expect(function() { - GeometryFilters.computeTangentAndBinormal(new Geometry({ + GeometryPipeline.computeTangentAndBinormal(new Geometry({ attributes: {} })); }).toThrow(); }); - it('GeometryFilters.computeTangentAndBinormal throws when geometry.attributes.position.values is undefined', function() { + it('GeometryPipeline.computeTangentAndBinormal throws when geometry.attributes.position.values is undefined', function() { expect(function() { - GeometryFilters.computeTangentAndBinormal(new Geometry({ + GeometryPipeline.computeTangentAndBinormal(new Geometry({ attributes: { position: new GeometryAttribute() } @@ -742,9 +742,9 @@ defineSuite([ }).toThrow(); }); - it('GeometryFilters.computeTangentAndBinormal throws when geometry.attributes.position.componentsPerAttribute is not 3', function() { + it('GeometryPipeline.computeTangentAndBinormal throws when geometry.attributes.position.componentsPerAttribute is not 3', function() { expect(function() { - GeometryFilters.computeTangentAndBinormal(new Geometry({ + GeometryPipeline.computeTangentAndBinormal(new Geometry({ attributes: { position: new GeometryAttribute({ values: [3, 2, 1, 1, 2, 4], @@ -755,9 +755,9 @@ defineSuite([ }).toThrow(); }); - it('GeometryFilters.computeTangentAndBinormal throws when geometry.attributes.position.values is not a multiple of 3', function() { + it('GeometryPipeline.computeTangentAndBinormal throws when geometry.attributes.position.values is not a multiple of 3', function() { expect(function() { - GeometryFilters.computeTangentAndBinormal(new Geometry({ + GeometryPipeline.computeTangentAndBinormal(new Geometry({ attributes: { position: new GeometryAttribute({ values: [3, 2, 1, 1, 2, 4, 3], @@ -768,9 +768,9 @@ defineSuite([ }).toThrow(); }); - it('GeometryFilters.computeTangentAndBinormal throws when geometry.attributes.normal is undefined', function() { + it('GeometryPipeline.computeTangentAndBinormal throws when geometry.attributes.normal is undefined', function() { expect(function() { - GeometryFilters.computeTangentAndBinormal(new Geometry({ + GeometryPipeline.computeTangentAndBinormal(new Geometry({ attributes: { position: new GeometryAttribute({ values: [0, 0, 0, 1, 0, 0, 0, 1, 0], @@ -781,9 +781,9 @@ defineSuite([ }).toThrow(); }); - it('GeometryFilters.computeTangentAndBinormal throws when geometry.attributes.normal.values is undefined', function() { + it('GeometryPipeline.computeTangentAndBinormal throws when geometry.attributes.normal.values is undefined', function() { expect(function() { - GeometryFilters.computeTangentAndBinormal(new Geometry({ + GeometryPipeline.computeTangentAndBinormal(new Geometry({ attributes: { position: new GeometryAttribute({ values: [0, 0, 0, 1, 0, 0, 0, 1, 0], @@ -795,9 +795,9 @@ defineSuite([ }).toThrow(); }); - it('GeometryFilters.computeTangentAndBinormal throws when geometry.attributes.normal.componentsPerAttribute is not 3', function() { + it('GeometryPipeline.computeTangentAndBinormal throws when geometry.attributes.normal.componentsPerAttribute is not 3', function() { expect(function() { - GeometryFilters.computeTangentAndBinormal(new Geometry({ + GeometryPipeline.computeTangentAndBinormal(new Geometry({ attributes: { position: new GeometryAttribute({ values: [3, 2, 1, 1, 2, 4], @@ -812,9 +812,9 @@ defineSuite([ }).toThrow(); }); - it('GeometryFilters.computeTangentAndBinormal throws when geometry.attributes.normal.values is not a multiple of 3', function() { + it('GeometryPipeline.computeTangentAndBinormal throws when geometry.attributes.normal.values is not a multiple of 3', function() { expect(function() { - GeometryFilters.computeTangentAndBinormal(new Geometry({ + GeometryPipeline.computeTangentAndBinormal(new Geometry({ attributes: { position: new GeometryAttribute({ values: [3, 2, 1, 1, 2, 3], @@ -829,9 +829,9 @@ defineSuite([ }).toThrow(); }); - it('GeometryFilters.computeTangentAndBinormal throws when geometry.attributes.st is undefined', function() { + it('GeometryPipeline.computeTangentAndBinormal throws when geometry.attributes.st is undefined', function() { expect(function() { - GeometryFilters.computeTangentAndBinormal(new Geometry( { + GeometryPipeline.computeTangentAndBinormal(new Geometry( { attributes: { position: new GeometryAttribute({ values: [0, 0, 0, 1, 0, 0, 0, 1, 0], @@ -847,9 +847,9 @@ defineSuite([ }).toThrow(); }); - it('GeometryFilters.computeTangentAndBinormal throws when geometry.attributes.normal.values is undefined', function() { + it('GeometryPipeline.computeTangentAndBinormal throws when geometry.attributes.normal.values is undefined', function() { expect(function() { - GeometryFilters.computeTangentAndBinormal(new Geometry( { + GeometryPipeline.computeTangentAndBinormal(new Geometry( { attributes: { position: new GeometryAttribute({ values: [0, 0, 0, 1, 0, 0, 0, 1, 0], @@ -865,9 +865,9 @@ defineSuite([ }).toThrow(); }); - it('GeometryFilters.computeTangentAndBinormal throws when geometry.attributes.st.componentsPerAttribute is not 2', function() { + it('GeometryPipeline.computeTangentAndBinormal throws when geometry.attributes.st.componentsPerAttribute is not 2', function() { expect(function() { - GeometryFilters.computeTangentAndBinormal(new Geometry( { + GeometryPipeline.computeTangentAndBinormal(new Geometry( { attributes: { position: new GeometryAttribute({ values: [0, 0, 0, 1, 0, 0, 0, 1, 0], @@ -886,9 +886,9 @@ defineSuite([ }).toThrow(); }); - it('GeometryFilters.computeTangentAndBinormal throws when geometry.attributes.st.values is not a multiple of 2', function() { + it('GeometryPipeline.computeTangentAndBinormal throws when geometry.attributes.st.values is not a multiple of 2', function() { expect(function() { - GeometryFilters.computeTangentAndBinormal(new Geometry( { + GeometryPipeline.computeTangentAndBinormal(new Geometry( { attributes: { position: new GeometryAttribute({ values: [0, 0, 0, 1, 0, 0, 0, 1, 0], @@ -907,7 +907,7 @@ defineSuite([ }).toThrow(); }); - it('GeometryFilters.computeTangentAndBinormal does not compute tangent and binormals when geometry.indexList is undefined', function() { + it('GeometryPipeline.computeTangentAndBinormal does not compute tangent and binormals when geometry.indexList is undefined', function() { var geometry = new Geometry({ attributes: { position: new GeometryAttribute({ @@ -926,13 +926,13 @@ defineSuite([ } }); - geometry = GeometryFilters.computeTangentAndBinormal(geometry); + geometry = GeometryPipeline.computeTangentAndBinormal(geometry); expect(typeof geometry.attributes.tangent === 'undefined').toEqual(true); expect(typeof geometry.attributes.binormal === 'undefined').toEqual(true); }); - it('GeometryFilters.computeTangentAndBinormal does not compute tangent and binormals when primitive type is not triangle', function() { + it('GeometryPipeline.computeTangentAndBinormal does not compute tangent and binormals when primitive type is not triangle', function() { var geometry = new Geometry({ attributes: { position: new GeometryAttribute({ @@ -954,13 +954,13 @@ defineSuite([ primitiveType: PrimitiveType.TRIANGLE_STRIP }); - geometry = GeometryFilters.computeTangentAndBinormal(geometry); + geometry = GeometryPipeline.computeTangentAndBinormal(geometry); expect(typeof geometry.attributes.tangent === 'undefined').toEqual(true); expect(typeof geometry.attributes.binormal === 'undefined').toEqual(true); }); - it('GeometryFilters.computeTangentAndBinormal computes tangent and binormal for one triangle', function() { + it('GeometryPipeline.computeTangentAndBinormal computes tangent and binormal for one triangle', function() { var geometry = new Geometry({ attributes: { position: new GeometryAttribute({ @@ -976,14 +976,14 @@ defineSuite([ primitiveType: PrimitiveType.TRIANGLES }); - geometry = GeometryFilters.computeNormal(geometry); - geometry = GeometryFilters.computeTangentAndBinormal(geometry); + geometry = GeometryPipeline.computeNormal(geometry); + geometry = GeometryPipeline.computeTangentAndBinormal(geometry); expect(geometry.attributes.tangent.values).toEqual([1, 0, 0, 1, 0, 0, 1, 0, 0]); expect(geometry.attributes.binormal.values).toEqual([0, 1, 0, 0, 1, 0, 0, 1, 0]); }); - it('GeometryFilters.computeTangentAndBinormal computes tangent and binormal for two triangles', function() { + it('GeometryPipeline.computeTangentAndBinormal computes tangent and binormal for two triangles', function() { var geometry = new Geometry({ attributes: { position: new GeometryAttribute({ @@ -999,8 +999,8 @@ defineSuite([ primitiveType: PrimitiveType.TRIANGLES }); - geometry = GeometryFilters.computeNormal(geometry); - geometry = GeometryFilters.computeTangentAndBinormal(geometry); + geometry = GeometryPipeline.computeNormal(geometry); + geometry = GeometryPipeline.computeTangentAndBinormal(geometry); expect(geometry.attributes.tangent.values).toEqualEpsilon([0.7071067811865475, 0, 0.7071067811865475, 0, 1, 0, 0, 1, 0, @@ -1011,13 +1011,13 @@ defineSuite([ -0.4082482904638631, -0.8164965809277261, 0.4082482904638631], CesiumMath.EPSILON8); }); - it ('GeometryFilters.computeTangentAndBinormal computes tangent and binormal for an EllipsoidGeometry', function() { + it ('GeometryPipeline.computeTangentAndBinormal computes tangent and binormal for an EllipsoidGeometry', function() { var geometry = new EllipsoidGeometry(); var expected = new EllipsoidGeometry({ vertexFormat: VertexFormat.ALL }); - geometry = GeometryFilters.computeTangentAndBinormal(geometry); + geometry = GeometryPipeline.computeTangentAndBinormal(geometry); expect(geometry.attributes.tangent.values.slice(1000,1200)).toEqualEpsilon(expected.attributes.tangent.values.slice(1000,1200), CesiumMath.EPSILON1); expect(geometry.attributes.binormal.values.slice(1000,1200)).toEqualEpsilon(expected.attributes.binormal.values.slice(1000,1200), CesiumMath.EPSILON1); }); diff --git a/Specs/Renderer/VertexArrayFactorySpec.js b/Specs/Renderer/VertexArrayFactorySpec.js index 960ed039dacc..4eb3c180ed66 100644 --- a/Specs/Renderer/VertexArrayFactorySpec.js +++ b/Specs/Renderer/VertexArrayFactorySpec.js @@ -5,7 +5,7 @@ defineSuite([ 'Core/ComponentDatatype', 'Core/Geometry', 'Core/GeometryAttribute', - 'Core/GeometryFilters', + 'Core/GeometryPipeline', 'Core/PrimitiveType', 'Core/IndexDatatype', 'Renderer/BufferUsage', @@ -17,7 +17,7 @@ defineSuite([ ComponentDatatype, Geometry, GeometryAttribute, - GeometryFilters, + GeometryPipeline, PrimitiveType, IndexDatatype, BufferUsage, @@ -70,7 +70,7 @@ defineSuite([ var va = context.createVertexArrayFromGeometry({ geometry : geometry, - attributeIndices : GeometryFilters.createAttributeIndices(geometry) + attributeIndices : GeometryPipeline.createAttributeIndices(geometry) }); expect(va.getNumberOfAttributes()).toEqual(1); @@ -99,7 +99,7 @@ defineSuite([ var va = context.createVertexArrayFromGeometry({ geometry : geometry, - attributeIndices : GeometryFilters.createAttributeIndices(geometry), + attributeIndices : GeometryPipeline.createAttributeIndices(geometry), vertexLayout : VertexLayout.INTERLEAVED, bufferUsage : BufferUsage.STATIC_DRAW }); @@ -135,7 +135,7 @@ defineSuite([ var va = context.createVertexArrayFromGeometry({ geometry : geometry, - attributeIndices : GeometryFilters.createAttributeIndices(geometry) + attributeIndices : GeometryPipeline.createAttributeIndices(geometry) }); expect(va.getNumberOfAttributes()).toEqual(2); @@ -176,7 +176,7 @@ defineSuite([ var va = context.createVertexArrayFromGeometry({ geometry : geometry, - attributeIndices : GeometryFilters.createAttributeIndices(geometry), + attributeIndices : GeometryPipeline.createAttributeIndices(geometry), vertexLayout : VertexLayout.INTERLEAVED }); @@ -220,7 +220,7 @@ defineSuite([ var va = context.createVertexArrayFromGeometry({ geometry : geometry, - attributeIndices : GeometryFilters.createAttributeIndices(geometry), + attributeIndices : GeometryPipeline.createAttributeIndices(geometry), vertexLayout : VertexLayout.INTERLEAVED }); @@ -267,7 +267,7 @@ defineSuite([ } }); - var attributeIndices = GeometryFilters.createAttributeIndices(geometry); + var attributeIndices = GeometryPipeline.createAttributeIndices(geometry); var va = context.createVertexArrayFromGeometry({ geometry : geometry, attributeIndices : attributeIndices, @@ -327,7 +327,7 @@ defineSuite([ } }); - var attributeIndices = GeometryFilters.createAttributeIndices(geometry); + var attributeIndices = GeometryPipeline.createAttributeIndices(geometry); var va = context.createVertexArrayFromGeometry({ geometry : geometry, attributeIndices : attributeIndices, @@ -401,7 +401,7 @@ defineSuite([ } }); - var attributeIndices = GeometryFilters.createAttributeIndices(geometry); + var attributeIndices = GeometryPipeline.createAttributeIndices(geometry); var va = context.createVertexArrayFromGeometry({ geometry : geometry, attributeIndices : attributeIndices, @@ -469,7 +469,7 @@ defineSuite([ } }); - var attributeIndices = GeometryFilters.createAttributeIndices(geometry); + var attributeIndices = GeometryPipeline.createAttributeIndices(geometry); var va = context.createVertexArrayFromGeometry({ geometry : geometry, attributeIndices : attributeIndices, diff --git a/Specs/Scene/MultifrustumSpec.js b/Specs/Scene/MultifrustumSpec.js index edbb91318dba..51618232958d 100644 --- a/Specs/Scene/MultifrustumSpec.js +++ b/Specs/Scene/MultifrustumSpec.js @@ -11,7 +11,7 @@ defineSuite([ 'Core/defaultValue', 'Core/Math', 'Core/Matrix4', - 'Core/GeometryFilters', + 'Core/GeometryPipeline', 'Core/PrimitiveType', 'Renderer/BlendingState', 'Renderer/BufferUsage', @@ -32,7 +32,7 @@ defineSuite([ defaultValue, CesiumMath, Matrix4, - GeometryFilters, + GeometryPipeline, PrimitiveType, BlendingState, BufferUsage, @@ -214,7 +214,7 @@ defineSuite([ minimumCorner: minimumCorner, maximumCorner: maximumCorner }); - var attributeIndices = GeometryFilters.createAttributeIndices(geometry); + var attributeIndices = GeometryPipeline.createAttributeIndices(geometry); this._va = context.createVertexArrayFromGeometry({ geometry: geometry, attributeIndices: attributeIndices, From c7185e1fe2f7ed94cfbc1bb4f2830dfbbca730dd Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Fri, 7 Jun 2013 13:50:54 -0400 Subject: [PATCH 151/306] Renamed cleanUp to removeDuplicates --- CHANGES.md | 22 +++++++++++++--------- Source/Core/PolygonGeometry.js | 4 ++-- Source/Core/PolygonPipeline.js | 2 +- Source/Core/PolylinePipeline.js | 2 +- Source/Core/WallGeometry.js | 2 +- Source/Scene/Polygon.js | 2 +- Specs/Core/PolygonPipelineSpec.js | 16 ++++++++-------- 7 files changed, 27 insertions(+), 23 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 4c392c5aa46f..69f15e8035b6 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -7,11 +7,6 @@ Beta Releases ### TODO * Breaking changes: - * Changed all widgets to use ECMAScript 5 properties. All public observable properties now must be accessed and assigned as if they were normal properties, instead of being called as functions. For example: - * `clockViewModel.shouldAnimate()` -> `clockViewModel.shouldAnimate` - * `clockViewModel.shouldAnimate(true);` -> `clockViewModel.shouldAnimate = true;` - * `ImageryProviderViewModel.fromConstants` has been removed. Use the `ImageryProviderViewModel` constructor directly. - * Renamed the `transitioner` property on `CesiumWidget`, `HomeButton`, and `ScreenModePicker` to `sceneTrasitioner` to be consistent with property naming convention. * Replaced tessellators and meshes with geometry. In particular: * Replaced `CubeMapEllipsoidTessellator` with `EllipsoidGeometry`. * Replaced `BoxTessellator` with `BoxGeometry`. @@ -23,17 +18,26 @@ Beta Releases * Renamed `ComponentDatatype.*.toTypedArray` to `ComponentDatatype.*.createTypedArray`. * Replaced `Uniform.getFrameNumber` and `Uniform.getTime` with `Uniform.getFrameState`, which returns the full frame state. * Removed `Polygon.configureExtent`. + * Renamed `PolygonPipeline.cleanUp` to `PolygonPipeline.removeDuplicates`. * Added `height` parameter to `BoundingSphere.fromExtent3D`. * Added `height` parameter to `Extent.subsample`. -* Improved the performance of drawing polygons created with `configureFromPolygonHierarchy`. +* Added `WallGeometry`, `PolygonGeometry`, `EllipseGeometry`, and `CircleGeometry`. * Added `GeometryPipeline.combine` to combine meshes for better batching. * Added `GeometryPipeline.computeNormal` to find the normals of vertices in a mesh. * Added `GeometryPipeline.computeTangentAndBinormal` to find the tangent and binormal vectors of vertices in a mesh. * Added `BoundingSphere.fromEllipsoid`. -* Added renderer support for `OES_element_index_uint`, which can improve performance by reducing batch sizes. +* Added `PolylinePipeline.removeDuplicates`. * Added `czm_tangentToEyeSpaceMatrix` built-in GLSL function. -* Added `WallGeometry` and `PolygonGeometry`. -* Added `EllipseGeometry` and `CircleGeometry`. +* Improved the performance of drawing polygons created with `configureFromPolygonHierarchy`. + +### b18 - 2013-07-01 + +* Breaking changes: + * Changed all widgets to use ECMAScript 5 properties. All public observable properties now must be accessed and assigned as if they were normal properties, instead of being called as functions. For example: + * `clockViewModel.shouldAnimate()` -> `clockViewModel.shouldAnimate` + * `clockViewModel.shouldAnimate(true);` -> `clockViewModel.shouldAnimate = true;` + * `ImageryProviderViewModel.fromConstants` has been removed. Use the `ImageryProviderViewModel` constructor directly. + * Renamed the `transitioner` property on `CesiumWidget`, `HomeButton`, and `ScreenModePicker` to `sceneTrasitioner` to be consistent with property naming convention. ### b17 - 2013-06-03 diff --git a/Source/Core/PolygonGeometry.js b/Source/Core/PolygonGeometry.js index d5b82aaba841..636739dd5c04 100644 --- a/Source/Core/PolygonGeometry.js +++ b/Source/Core/PolygonGeometry.js @@ -90,7 +90,7 @@ define([ var createGeometryFromPositionsPositions = []; function createGeometryFromPositions(ellipsoid, positions, boundingSphere, granularity) { - var cleanedPositions = PolygonPipeline.cleanUp(positions); + var cleanedPositions = PolygonPipeline.removeDuplicates(positions); if (cleanedPositions.length < 3) { // Duplicate positions result in not enough positions to form a polygon. return undefined; @@ -293,7 +293,7 @@ define([ if (vertexFormat.st || vertexFormat.normal || vertexFormat.tangent || vertexFormat.binormal) { // PERFORMANCE_IDEA: Compute before subdivision, then just interpolate during subdivision. // PERFORMANCE_IDEA: Compute with createGeometryFromPositions() for fast path when there's no holes. - var cleanedPositions = PolygonPipeline.cleanUp(outerPositions); + var cleanedPositions = PolygonPipeline.removeDuplicates(outerPositions); var tangentPlane = EllipsoidTangentPlane.fromPoints(cleanedPositions, ellipsoid); var boundingRectangle = computeBoundingRectangle(tangentPlane, outerPositions, stRotation, scratchBoundingRectangle); diff --git a/Source/Core/PolygonPipeline.js b/Source/Core/PolygonPipeline.js index 1cac23716c27..0227b05b2434 100644 --- a/Source/Core/PolygonPipeline.js +++ b/Source/Core/PolygonPipeline.js @@ -410,7 +410,7 @@ define([ * @exception {DeveloperError} positions is required. * @exception {DeveloperError} At least three positions are required. */ - cleanUp : function(positions) { + removeDuplicates : function(positions) { if (typeof positions === 'undefined') { throw new DeveloperError('positions is required.'); } diff --git a/Source/Core/PolylinePipeline.js b/Source/Core/PolylinePipeline.js index 20c8862ada4c..52df7c5d65d4 100644 --- a/Source/Core/PolylinePipeline.js +++ b/Source/Core/PolylinePipeline.js @@ -117,7 +117,7 @@ define([ /** * DOC_TBA */ - PolylinePipeline.cleanUp = function(positions) { + PolylinePipeline.removeDuplicates = function(positions) { if (typeof positions === 'undefined') { throw new DeveloperError('positions is required.'); } diff --git a/Source/Core/WallGeometry.js b/Source/Core/WallGeometry.js index d0628512cd3c..09c4879b753b 100644 --- a/Source/Core/WallGeometry.js +++ b/Source/Core/WallGeometry.js @@ -92,7 +92,7 @@ define([ throw new DeveloperError('positions and terrain points must have the same length.'); } - wallPositions = PolylinePipeline.cleanUp(wallPositions); + wallPositions = PolylinePipeline.removeDuplicates(wallPositions); if (wallPositions.length >= 3) { // Order positions counter-clockwise var tangentPlane = EllipsoidTangentPlane.fromPoints(wallPositions, ellipsoid); diff --git a/Source/Scene/Polygon.js b/Source/Scene/Polygon.js index a3aa93faa8f8..ffe83e621969 100644 --- a/Source/Scene/Polygon.js +++ b/Source/Scene/Polygon.js @@ -496,7 +496,7 @@ define([ var createGeometryFromPositionsBoundingRectangle = new BoundingRectangle(); function createGeometryFromPositions(polygon, positions, angle, boundingSphere, outerPositions) { - var cleanedPositions = PolygonPipeline.cleanUp(positions); + var cleanedPositions = PolygonPipeline.removeDuplicates(positions); if (cleanedPositions.length < 3) { // Duplicate positions result in not enough positions to form a polygon. return undefined; diff --git a/Specs/Core/PolygonPipelineSpec.js b/Specs/Core/PolygonPipelineSpec.js index 21828353e419..bf967b6e0cd4 100644 --- a/Specs/Core/PolygonPipelineSpec.js +++ b/Specs/Core/PolygonPipelineSpec.js @@ -18,8 +18,8 @@ defineSuite([ "use strict"; /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/ - it('cleanUp removes duplicate points', function() { - var positions = PolygonPipeline.cleanUp([ + it('removeDuplicates removes duplicate points', function() { + var positions = PolygonPipeline.removeDuplicates([ new Cartesian3(1.0, 1.0, 1.0), new Cartesian3(2.0, 2.0, 2.0), new Cartesian3(2.0, 2.0, 2.0), @@ -33,8 +33,8 @@ defineSuite([ ]); }); - it('cleanUp removes duplicate first and last points', function() { - var positions = PolygonPipeline.cleanUp([ + it('removeDuplicates removes duplicate first and last points', function() { + var positions = PolygonPipeline.removeDuplicates([ new Cartesian3(1.0, 1.0, 1.0), new Cartesian3(2.0, 2.0, 2.0), new Cartesian3(3.0, 3.0, 3.0), @@ -48,15 +48,15 @@ defineSuite([ ]); }); - it('cleanUp throws without positions', function() { + it('removeDuplicates throws without positions', function() { expect(function() { - PolygonPipeline.cleanUp(); + PolygonPipeline.removeDuplicates(); }).toThrow(); }); - it('cleanUp throws without three positions', function() { + it('removeDuplicates throws without three positions', function() { expect(function() { - PolygonPipeline.cleanUp([Cartesian3.ZERO, Cartesian3.ZERO]); + PolygonPipeline.removeDuplicates([Cartesian3.ZERO, Cartesian3.ZERO]); }).toThrow(); }); From e72a2c556c1fc27374ec7bb521dd8876b8db320f Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Fri, 7 Jun 2013 14:04:23 -0400 Subject: [PATCH 152/306] Added tests for removeDuplicates --- Specs/Core/PolylinePipelineSpec.js | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/Specs/Core/PolylinePipelineSpec.js b/Specs/Core/PolylinePipelineSpec.js index 7e45362b702b..1c6b25c9f465 100644 --- a/Specs/Core/PolylinePipelineSpec.js +++ b/Specs/Core/PolylinePipelineSpec.js @@ -49,4 +49,31 @@ defineSuite([ expect(segments.lengths[0]).toEqual(2); expect(segments.lengths[1]).toEqual(2); }); + + it('removeDuplicates to return one positions', function() { + var positions = [Cartesian3.ZERO]; + var nonDuplicatePositions = PolylinePipeline.removeDuplicates(positions); + expect(nonDuplicatePositions).toEqual(positions); + }); + + it('removeDuplicates to remove duplicates', function() { + var positions = [ + new Cartesian3(1.0, 1.0, 1.0), + new Cartesian3(1.0, 1.0, 1.0), + new Cartesian3(2.0, 2.0, 2.0), + new Cartesian3(3.0, 3.0, 3.0), + new Cartesian3(3.0, 3.0, 3.0)]; + var expectedPositions = [ + new Cartesian3(1.0, 1.0, 1.0), + new Cartesian3(2.0, 2.0, 2.0), + new Cartesian3(3.0, 3.0, 3.0)]; + var nonDuplicatePositions = PolylinePipeline.removeDuplicates(positions); + expect(nonDuplicatePositions).toEqual(expectedPositions); + }); + + it('removeDuplicates throws without positions', function() { + expect(function() { + PolylinePipeline.removeDuplicates(); + }).toThrow(); + }); }); \ No newline at end of file From 86ce69ce97f61196bb741a71a62ae035000dc2d3 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Fri, 7 Jun 2013 14:17:12 -0400 Subject: [PATCH 153/306] Added doc for removeDuplicates --- Source/Core/PolylinePipeline.js | 18 +++++++++++++++++- Specs/Core/PolylinePipelineSpec.js | 2 ++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/Source/Core/PolylinePipeline.js b/Source/Core/PolylinePipeline.js index 52df7c5d65d4..77d78f6bf1cb 100644 --- a/Source/Core/PolylinePipeline.js +++ b/Source/Core/PolylinePipeline.js @@ -115,7 +115,23 @@ define([ }; /** - * DOC_TBA + * Removes adjacent duplicate positions in an array of positions. + * + * @memberof PolylinePipeline + * + * @param {Array} positions The array of positions. Each element is usually a {@see Cartesian3}, but all that is required is that the object have an equals function. + * + * @returns {Object} A new array of positions with no adjacent duplicate positions. Positions are shallow copied. + * + * @exception {DeveloperError} positions is required. + * + * @example + * // Returns [(1.0, 1.0, 1.0), (2.0, 2.0, 2.0)] + * var positions = [ + * new Cartesian3(1.0, 1.0, 1.0), + * new Cartesian3(1.0, 1.0, 1.0), + * new Cartesian3(2.0, 2.0, 2.0)]; + * var nonDuplicatePositions = PolylinePipeline.removeDuplicates(positions); */ PolylinePipeline.removeDuplicates = function(positions) { if (typeof positions === 'undefined') { diff --git a/Specs/Core/PolylinePipelineSpec.js b/Specs/Core/PolylinePipelineSpec.js index 1c6b25c9f465..73d4d56a212a 100644 --- a/Specs/Core/PolylinePipelineSpec.js +++ b/Specs/Core/PolylinePipelineSpec.js @@ -53,6 +53,7 @@ defineSuite([ it('removeDuplicates to return one positions', function() { var positions = [Cartesian3.ZERO]; var nonDuplicatePositions = PolylinePipeline.removeDuplicates(positions); + expect(nonDuplicatePositions).not.toBe(positions); expect(nonDuplicatePositions).toEqual(positions); }); @@ -68,6 +69,7 @@ defineSuite([ new Cartesian3(2.0, 2.0, 2.0), new Cartesian3(3.0, 3.0, 3.0)]; var nonDuplicatePositions = PolylinePipeline.removeDuplicates(positions); + expect(nonDuplicatePositions).not.toBe(expectedPositions); expect(nonDuplicatePositions).toEqual(expectedPositions); }); From bad38b7e252370f9355a92bcfb5b812ae10db6b9 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Tue, 11 Jun 2013 09:20:36 -0400 Subject: [PATCH 154/306] Another GeometryPipeline rename --- Apps/Sandcastle/gallery/Custom Rendering.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Apps/Sandcastle/gallery/Custom Rendering.html b/Apps/Sandcastle/gallery/Custom Rendering.html index 63b58a3abf0f..d710e20dbf1f 100644 --- a/Apps/Sandcastle/gallery/Custom Rendering.html +++ b/Apps/Sandcastle/gallery/Custom Rendering.html @@ -96,11 +96,11 @@ var minimumCorner = maximumCorner.negate(); Cesium.BoundingSphere.fromPoints([minimumCorner, maximumCorner], colorCommand.boundingVolume); - var geometry = Cesium.GeometryFilters.toWireframe(new Cesium.BoxGeometry({ + var geometry = Cesium.GeometryPipeline.toWireframe(new Cesium.BoxGeometry({ minimumCorner : minimumCorner, maximumCorner : maximumCorner })); - var attributeIndices = Cesium.GeometryFilters.createAttributeIndices(geometry); + var attributeIndices = Cesium.GeometryPipeline.createAttributeIndices(geometry); colorCommand.vertexArray = pickCommand.vertexArray = context.createVertexArrayFromGeometry({ geometry : geometry, @@ -204,7 +204,7 @@ var maximumCorner = dimensions.multiplyByScalar(0.5); var minimumCorner = maximumCorner.negate(); - var geometry = Cesium.GeometryFilters.toWireframe(new Cesium.BoxGeometry({ + var geometry = Cesium.GeometryPipeline.toWireframe(new Cesium.BoxGeometry({ minimumCorner : minimumCorner, maximumCorner : maximumCorner })); From e6397d5a93a89bd8bce438f4137361819508fdb4 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Tue, 11 Jun 2013 13:55:22 -0400 Subject: [PATCH 155/306] GeometryPipeline improvements --- CHANGES.md | 1 + Source/Core/GeometryPipeline.js | 504 ++++++++++++++--------------- Source/Scene/Primitive.js | 4 +- Specs/Core/GeometryPipelineSpec.js | 267 +++++++++------ 4 files changed, 424 insertions(+), 352 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 38a203d68f48..ea333440c573 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -14,6 +14,7 @@ Beta Releases * Removed `PlaneTessellator`. It was incomplete and not used. * Renamed `MeshFilters` to `GeometryPipeline`. * Renamed `MeshFilters.toWireframeInPlace` to `GeometryPipeline.toWireframe`. + * Removed `MeshFilters.mapAttributeIndices`. It was not used. * Renamed `Context.createVertexArrayFromMesh` to `Context.createVertexArrayFromGeometry`. Likewise, renamed `mesh` constructor property to `geometry`. * Renamed `ComponentDatatype.*.toTypedArray` to `ComponentDatatype.*.createTypedArray`. * Replaced `Uniform.getFrameNumber` and `Uniform.getTime` with `Uniform.getFrameState`, which returns the full frame state. diff --git a/Source/Core/GeometryPipeline.js b/Source/Core/GeometryPipeline.js index a634ba29a864..45846fc11054 100644 --- a/Source/Core/GeometryPipeline.js +++ b/Source/Core/GeometryPipeline.js @@ -13,7 +13,7 @@ define([ './Tipsify', './BoundingSphere', './Geometry', - './GeometryAttribute', + './GeometryAttribute' ], function( defaultValue, DeveloperError, @@ -32,270 +32,272 @@ define([ "use strict"; /** - * DOC_TBA + * Content pipeline functions for geometries. These functions generally modify geometry in place. * * @exports GeometryPipeline * + * @see Geometry * @see Context#createVertexArrayFromGeometry */ var GeometryPipeline = {}; - /** - * Converts a geometry's triangle indices to line indices. The geometry's indexList with - * a primitive type of triangles, triangleStrip, or trangleFan is converted to a - * list of indices with a primitive type of lines. - *

    - * The geometry argument should use the standard layout like the geometry returned by {@link BoxGeometry}. - *

    - * This filter is commonly used to create a wireframe geometry for visual debugging. - * - * @param {Geometry} geometry The geometry to filter, which is modified in place. - * - * @returns The modified geometry argument, with its triangle indices converted to lines. - * - * @example - * var geometry = new BoxGeometry(); - * geometry = GeometryPipeline.toWireframe(geometry); - */ - GeometryPipeline.toWireframe = function(geometry) { - function addTriangle(lines, i0, i1, i2) { - lines.push(i0); - lines.push(i1); - - lines.push(i1); - lines.push(i2); + function addTriangle(lines, i0, i1, i2) { + lines.push(i0); + lines.push(i1); - lines.push(i2); - lines.push(i0); - } + lines.push(i1); + lines.push(i2); - function trianglesToLines(triangles) { - var lines = []; - var count = triangles.length; - for ( var i = 0; i < count; i += 3) { - addTriangle(lines, triangles[i], triangles[i + 1], triangles[i + 2]); - } + lines.push(i2); + lines.push(i0); + } - return lines; + function trianglesToLines(triangles) { + var lines = []; + var count = triangles.length; + for ( var i = 0; i < count; i += 3) { + addTriangle(lines, triangles[i], triangles[i + 1], triangles[i + 2]); } - function triangleStripToLines(triangles) { - var lines = []; - var count = triangles.length; + return lines; + } - if (count >= 3) { - addTriangle(lines, triangles[0], triangles[1], triangles[2]); + function triangleStripToLines(triangles) { + var lines = []; + var count = triangles.length; - for ( var i = 3; i < count; ++i) { - addTriangle(lines, triangles[i - 1], triangles[i], triangles[i - 2]); - } - } + if (count >= 3) { + addTriangle(lines, triangles[0], triangles[1], triangles[2]); - return lines; + for ( var i = 3; i < count; ++i) { + addTriangle(lines, triangles[i - 1], triangles[i], triangles[i - 2]); + } } - function triangleFanToLines(triangles) { - var lines = []; + return lines; + } - if (triangles.length > 0) { - var base = triangles[0]; - var count = triangles.length - 1; - for ( var i = 1; i < count; ++i) { - addTriangle(lines, base, triangles[i], triangles[i + 1]); - } - } + function triangleFanToLines(triangles) { + var lines = []; - return lines; + if (triangles.length > 0) { + var base = triangles[0]; + var count = triangles.length - 1; + for ( var i = 1; i < count; ++i) { + addTriangle(lines, base, triangles[i], triangles[i + 1]); + } } - if (typeof geometry !== 'undefined') { - var indices = geometry.indexList; - if (typeof indices !== 'undefined') { - switch (geometry.primitiveType) { - case PrimitiveType.TRIANGLES: - geometry.indexList = trianglesToLines(indices); - break; - case PrimitiveType.TRIANGLE_STRIP: - geometry.indexList = triangleStripToLines(indices); - break; - case PrimitiveType.TRIANGLE_FAN: - geometry.indexList = triangleFanToLines(indices); - break; - } + return lines; + } + + /** + * Converts a geometry's triangle indices to line indices. If the geometry has an indexList + * and its primitiveType is TRIANGLES, TRIANGLE_STRIP, + * TRIANGLE_FAN, it is converted to LINES; otherwise, the geometry is not changed. + *

    + * This is commonly used to create a wireframe geometry for visual debugging. + *

    + * + * @param {Geometry} geometry The geometry to modify, which is modified in place. + * + * @returns The modified geometry argument, with its triangle indices converted to lines. + * + * @exception {DeveloperError} geometry is required. + * + * @example + * geometry = GeometryPipeline.toWireframe(geometry); + */ + GeometryPipeline.toWireframe = function(geometry) { + if (typeof geometry === 'undefined') { + throw new DeveloperError('geometry is required.'); + } - geometry.primitiveType = PrimitiveType.LINES; + var indices = geometry.indexList; + if (typeof indices !== 'undefined') { + switch (geometry.primitiveType) { + case PrimitiveType.TRIANGLES: + geometry.indexList = trianglesToLines(indices); + break; + case PrimitiveType.TRIANGLE_STRIP: + geometry.indexList = triangleStripToLines(indices); + break; + case PrimitiveType.TRIANGLE_FAN: + geometry.indexList = triangleFanToLines(indices); + break; } + + geometry.primitiveType = PrimitiveType.LINES; } return geometry; }; /** - * DOC_TBA + * Creates an object that maps attribute names to unique indices for matching + * vertex attributes and shader programs. + * + * @param {Geometry} geometry The geometry, which is not modified, to create the object for. + * + * @returns An object with attribute name / index pairs. + * + * @exception {DeveloperError} geometry is required. + * + * @see Context#createVertexArrayFromGeometry + * @see ShaderCache + * + * @example + * var attributeIndices = GeometryPipeline.createAttributeIndices(geometry); + * // Example output + * // { + * // 'position' : 0, + * // 'normal' : 1 + * // } */ GeometryPipeline.createAttributeIndices = function(geometry) { - var indices = {}; - - if (typeof geometry !== 'undefined') { - var attributes = geometry.attributes; - var j = 0; - - for ( var name in attributes) { - if (attributes.hasOwnProperty(name)) { - indices[name] = j++; - } - } + if (typeof geometry === 'undefined') { + throw new DeveloperError('geometry is required.'); } - return indices; - }; + var indices = {}; - /** - * DOC_TBA - */ - GeometryPipeline.mapAttributeIndices = function(indices, map) { - var mappedIndices = {}; + var attributes = geometry.attributes; + var j = 0; - if (typeof indices !== 'undefined' && typeof map !== 'undefined') { - for ( var name in map) { - if (map.hasOwnProperty(name)) { - mappedIndices[map[name]] = indices[name]; - } + for ( var name in attributes) { + if (attributes.hasOwnProperty(name)) { + indices[name] = j++; } } - return mappedIndices; + return indices; }; /** - * Reorders a geometry's indices to achieve better performance from the GPU's pre-vertex-shader cache. - * Each list of indices in the geometry's indexList is reordered to keep the same index-vertex correspondence. - *

    - * The geometry argument should use the standard layout like the geometry returned by {@link BoxGeometry}. - *

    - - * @param {Geometry} geometry The geometry to filter, which is modified in place. + * Reorders a geometry's attributes and indexList to achieve better performance from the GPU's pre-vertex-shader cache. * - * @exception {DeveloperError} All geometry attribute lists must have the same number of attributes. + * @param {Geometry} geometry The geometry to modify, which is modified in place. + * + * @exception {DeveloperError} geometry is required. + * @exception {DeveloperError} Each attribute array in geometry.attributes must have the same number of attributes. * - * @returns The modified geometry argument, with its vertices and indices reordered for the GPU's pre-vertex-shader cache. + * @returns The modified geometry argument, with its attributes and indices reordered for the GPU's pre-vertex-shader cache. * * @see GeometryPipeline.reorderForPostVertexCache * * @example - * var geometry = new EllipsoidGeometry(...); * geometry = GeometryPipeline.reorderForPreVertexCache(geometry); */ GeometryPipeline.reorderForPreVertexCache = function(geometry) { - if (typeof geometry !== 'undefined') { - var numVertices = Geometry.computeNumberOfVertices(geometry); + if (typeof geometry === 'undefined') { + throw new DeveloperError('geometry is required.'); + } - var indexCrossReferenceOldToNew = []; - for ( var i = 0; i < numVertices; i++) { - indexCrossReferenceOldToNew[i] = -1; - } + var numVertices = Geometry.computeNumberOfVertices(geometry); + + var indexCrossReferenceOldToNew = new Array(numVertices); + for ( var i = 0; i < numVertices; i++) { + indexCrossReferenceOldToNew[i] = -1; + } - //Construct cross reference and reorder indices - var indexList = geometry.indexList; - if (typeof indexList !== 'undefined') { - var indicesIn = indexList; - var numIndices = indicesIn.length; - var indicesOut = []; - var intoIndicesIn = 0; - var intoIndicesOut = 0; - var nextIndex = 0; - var tempIndex; - while (intoIndicesIn < numIndices) { - tempIndex = indexCrossReferenceOldToNew[indicesIn[intoIndicesIn]]; - if (tempIndex !== -1) { - indicesOut[intoIndicesOut] = tempIndex; - } else { - tempIndex = indicesIn[intoIndicesIn]; - if (tempIndex >= numVertices) { - throw new DeveloperError('Input indices contains a value greater than or equal to the number of vertices'); - } - indexCrossReferenceOldToNew[tempIndex] = nextIndex; - - indicesOut[intoIndicesOut] = nextIndex; - ++nextIndex; + var indexList = geometry.indexList; + if (typeof indexList !== 'undefined') { + // Construct cross reference and reorder indices + var indicesIn = indexList; + var numIndices = indicesIn.length; + var indicesOut = []; + var intoIndicesIn = 0; + var intoIndicesOut = 0; + var nextIndex = 0; + var tempIndex; + while (intoIndicesIn < numIndices) { + tempIndex = indexCrossReferenceOldToNew[indicesIn[intoIndicesIn]]; + if (tempIndex !== -1) { + indicesOut[intoIndicesOut] = tempIndex; + } else { + tempIndex = indicesIn[intoIndicesIn]; + if (tempIndex >= numVertices) { + throw new DeveloperError('Each attribute array in geometry.attributes must have the same number of attributes.'); } - ++intoIndicesIn; - ++intoIndicesOut; + indexCrossReferenceOldToNew[tempIndex] = nextIndex; + + indicesOut[intoIndicesOut] = nextIndex; + ++nextIndex; } - geometry.indexList = indicesOut; + ++intoIndicesIn; + ++intoIndicesOut; } + geometry.indexList = indicesOut; + } - //Reorder Vertices - var attributes = geometry.attributes; - for ( var property in attributes) { - if (attributes.hasOwnProperty(property) && attributes[property].values) { - var elementsIn = attributes[property].values; - var intoElementsIn = 0; - var numComponents = attributes[property].componentsPerAttribute; - var elementsOut = []; - while (intoElementsIn < numVertices) { - var temp = indexCrossReferenceOldToNew[intoElementsIn]; - for (i = 0; i < numComponents; i++) { - elementsOut[numComponents * temp + i] = elementsIn[numComponents * intoElementsIn + i]; - } - ++intoElementsIn; + // Reorder attributes + var attributes = geometry.attributes; + for ( var property in attributes) { + if (attributes.hasOwnProperty(property) && attributes[property].values) { + var elementsIn = attributes[property].values; + var intoElementsIn = 0; + var numComponents = attributes[property].componentsPerAttribute; + var elementsOut = []; + while (intoElementsIn < numVertices) { + var temp = indexCrossReferenceOldToNew[intoElementsIn]; + for (i = 0; i < numComponents; i++) { + elementsOut[numComponents * temp + i] = elementsIn[numComponents * intoElementsIn + i]; } - attributes[property].values = elementsOut; + ++intoElementsIn; } + attributes[property].values = elementsOut; } } + return geometry; }; /** - * Reorders a geometry's indices to achieve better performance from the GPU's post vertex-shader cache by using the Tipsify algorithm. - * Each list of indices in the geometry's indexList is optimally reordered. - *

    - * The geometry argument should use the standard layout like the geometry returned by {@link BoxGeometry}. - *

    - - * @param {Geometry} geometry The geometry to filter, which is modified in place. + * Reorders a geometry's indexList to achieve better performance from the GPU's + * post vertex-shader cache by using the Tipsify algorithm. If the geometry primitiveType + * is not TRIANGLES or the geometry does not have an indexList, this function has no effect. + * + * @param {Geometry} geometry The geometry to modify, which is modified in place. * @param {Number} [cacheCapacity=24] The number of vertices that can be held in the GPU's vertex cache. * - * @exception {DeveloperError} Geometry's index list must be defined. - * @exception {DeveloperError} Geometry's index lists' lengths must each be a multiple of three. - * @exception {DeveloperError} Geometry's index list's maximum index value must be greater than zero. + * @exception {DeveloperError} geometry is required. * @exception {DeveloperError} cacheCapacity must be greater than two. * - * @returns The modified geometry argument, with its indices optimally reordered for the post-vertex-shader cache. + * @returns The modified geometry argument, with its indices reordered for the post-vertex-shader cache. * * @see GeometryPipeline.reorderForPreVertexCache - * @see Tipsify * @see * Fast Triangle Reordering for Vertex Locality and Reduced Overdraw * by Sander, Nehab, and Barczak * * @example - * var geometry = new EllipsoidGeometry(...); * geometry = GeometryPipeline.reorderForPostVertexCache(geometry); */ GeometryPipeline.reorderForPostVertexCache = function(geometry, cacheCapacity) { - if (typeof geometry !== 'undefined') { - var indices = geometry.indexList; - if (typeof indices !== 'undefined') { - var numIndices = indices.length; - var maximumIndex = 0; - for ( var j = 0; j < numIndices; j++) { - if (indices[j] > maximumIndex) { - maximumIndex = indices[j]; - } + if (typeof geometry === 'undefined') { + throw new DeveloperError('geometry is required.'); + } + + var indices = geometry.indexList; + if ((geometry.primitiveType === PrimitiveType.TRIANGLES) && (typeof indices !== 'undefined')) { + var numIndices = indices.length; + var maximumIndex = 0; + for ( var j = 0; j < numIndices; j++) { + if (indices[j] > maximumIndex) { + maximumIndex = indices[j]; } - geometry.indexList = Tipsify.tipsify({ - indices : indices, - maximumIndex : maximumIndex, - cacheSize : cacheCapacity - }); } + geometry.indexList = Tipsify.tipsify({ + indices : indices, + maximumIndex : maximumIndex, + cacheSize : cacheCapacity + }); } + return geometry; }; - GeometryPipeline._copyAttributesDescriptions = function(attributes) { + function copyAttributesDescriptions(attributes) { var newAttributes = {}; for ( var attribute in attributes) { @@ -311,7 +313,7 @@ define([ } return newAttributes; - }; + } function copyVertex(destinationAttributes, sourceAttributes, index) { for ( var attribute in sourceAttributes) { @@ -328,92 +330,86 @@ define([ /** * DOC_TBA. Old geometry is not guaranteed to be copied. * - * @exception {DeveloperError} geometry.primitiveType must equal to PrimitiveType.TRIANGLES. + * If the geometry does not have an indexList, this function has no effect. + * + * @exception {DeveloperError} geometry is required. + * @exception {DeveloperError} geometry.primitiveType must equal to PrimitiveType.TRIANGLES, PrimitiveType.LINES, or PrimitiveType.POINTS * @exception {DeveloperError} All geometry attribute lists must have the same number of attributes. */ GeometryPipeline.fitToUnsignedShortIndices = function(geometry) { - var geometries = []; - - if (typeof geometry !== 'undefined') { - if (geometry.primitiveType !== PrimitiveType.TRIANGLES) { - throw new DeveloperError('geometry.primitiveType must equal to PrimitiveType.TRIANGLES.'); - } - - var numberOfVertices = Geometry.computeNumberOfVertices(geometry); - - // If there's an index list and more than 64K attributes, it is possible that - // some indices are outside the range of unsigned short [0, 64K - 1] - var sixtyFourK = 64 * 1024; - if (typeof geometry.indexList !== 'undefined' && (numberOfVertices > sixtyFourK)) { - var oldToNewIndex = []; - var newIndices = []; - var currentIndex = 0; - var newAttributes = GeometryPipeline._copyAttributesDescriptions(geometry.attributes); - - var originalIndices = geometry.indexList; - var numberOfIndices = originalIndices.length; - - for ( var j = 0; j < numberOfIndices; j += 3) { - // It would be easy to extend this inter-loop to support all primitive-types. - - var x0 = originalIndices[j]; - var x1 = originalIndices[j + 1]; - var x2 = originalIndices[j + 2]; - - var i0 = oldToNewIndex[x0]; - if (typeof i0 === 'undefined') { - i0 = currentIndex++; - oldToNewIndex[x0] = i0; - - copyVertex(newAttributes, geometry.attributes, x0); - } - - var i1 = oldToNewIndex[x1]; - if (typeof i1 === 'undefined') { - i1 = currentIndex++; - oldToNewIndex[x1] = i1; + if (typeof geometry === 'undefined') { + throw new DeveloperError('geometry is required.'); + } - copyVertex(newAttributes, geometry.attributes, x1); - } + if ((typeof geometry.indexList !== 'undefined') && + ((geometry.primitiveType !== PrimitiveType.TRIANGLES) && + (geometry.primitiveType !== PrimitiveType.LINES) && + (geometry.primitiveType !== PrimitiveType.POINTS))) { + throw new DeveloperError('geometry.primitiveType must equal to PrimitiveType.TRIANGLES, PrimitiveType.LINES, or PrimitiveType.POINTS.'); + } - var i2 = oldToNewIndex[x2]; - if (typeof i2 === 'undefined') { - i2 = currentIndex++; - oldToNewIndex[x2] = i2; + var geometries = []; - copyVertex(newAttributes, geometry.attributes, x2); - } + // If there's an index list and more than 64K attributes, it is possible that + // some indices are outside the range of unsigned short [0, 64K - 1] + var numberOfVertices = Geometry.computeNumberOfVertices(geometry); + var sixtyFourK = 64 * 1024; + if (typeof geometry.indexList !== 'undefined' && (numberOfVertices > sixtyFourK)) { + var oldToNewIndex = []; + var newIndices = []; + var currentIndex = 0; + var newAttributes = copyAttributesDescriptions(geometry.attributes); + + var originalIndices = geometry.indexList; + var numberOfIndices = originalIndices.length; + + var indicesPerPrimitive; + + if (geometry.primitiveType === PrimitiveType.TRIANGLES) { + indicesPerPrimitive = 3; + } else if (geometry.primitiveType === PrimitiveType.LINES) { + indicesPerPrimitive = 2; + } else if (geometry.primitiveType === PrimitiveType.POINTS) { + indicesPerPrimitive = 1; + } - newIndices.push(i0); - newIndices.push(i1); - newIndices.push(i2); - - if (currentIndex + 3 > sixtyFourK) { - geometries.push(new Geometry({ - attributes : newAttributes, - indexList : newIndices, - primitiveType : geometry.primitiveType - })); - - // Reset for next vertex-array - oldToNewIndex = []; - newIndices = []; - currentIndex = 0; - newAttributes = GeometryPipeline._copyAttributesDescriptions(geometry.attributes); + for ( var j = 0; j < numberOfIndices; j += indicesPerPrimitive) { + for (var k = 0; k < indicesPerPrimitive; ++k) { + var x = originalIndices[j + k]; + var i = oldToNewIndex[x]; + if (typeof i === 'undefined') { + i = currentIndex++; + oldToNewIndex[x] = i; + copyVertex(newAttributes, geometry.attributes, x); } + newIndices.push(i); } - if (newIndices.length !== 0) { + if (currentIndex + indicesPerPrimitive > sixtyFourK) { geometries.push(new Geometry({ attributes : newAttributes, indexList : newIndices, primitiveType : geometry.primitiveType })); + + // Reset for next vertex-array + oldToNewIndex = []; + newIndices = []; + currentIndex = 0; + newAttributes = copyAttributesDescriptions(geometry.attributes); } - } else { - // No need to split into multiple geometries - geometries.push(geometry); } + + if (newIndices.length !== 0) { + geometries.push(new Geometry({ + attributes : newAttributes, + indexList : newIndices, + primitiveType : geometry.primitiveType + })); + } + } else { + // No need to split into multiple geometries + geometries.push(geometry); } return geometries; @@ -464,7 +460,7 @@ define([ * This is commonly used to create high-precision position vertex attributes. *

    * - * @param {Geometry} geometry The geometry to filter, which is modified in place. + * @param {Geometry} geometry The geometry to modify, which is modified in place. * @param {String} [attributeName='position'] The name of the attribute. * @param {String} [attributeHighName='positionHigh'] The name of the attribute for the encoded high bits. * @param {String} [attributeLowName='positionLow'] The name of the attribute for the encoded low bits. @@ -804,7 +800,7 @@ define([ * Computes the normals of all vertices in a geometry based on the normals of triangles that include the vertex. * This assumes a counter-clockwise vertex winding order. * - * @param {Geometry} geometry The geometry to filter, which is modified in place. + * @param {Geometry} geometry The geometry to modify, which is modified in place. * @param {Object} geometry.attributes.position * * @returns The modified geometry argument. @@ -948,7 +944,7 @@ define([ * * Based on: Lengyel, Eric. Computing Tangent Space Basis Vectors for an Arbitrary Mesh. Terathon Software 3D Graphics Library, 2001. * - * @param {Geometry} geometry The geometry for which to calculate tangents and binormals, which is modified in place. + * @param {Geometry} geometry The geometry to modify, which is modified in place. * @param {Object} geometry.attributes.position The vertices of the geometry * @param {Object} geometry.attributes.normal The normals of the vertices * @param {Object} geometry.attributes.st The texture coordinates diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index 6849a3583498..86adbefb4734 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -316,10 +316,10 @@ define([ // Split position for GPU RTE GeometryPipeline.encodeAttribute(geometry, 'position', 'positionHigh', 'positionLow'); - if (!context.getElementIndexUint()) { +// if (!context.getElementIndexUint()) { // Break into multiple geometries to fit within unsigned short indices if needed return GeometryPipeline.fitToUnsignedShortIndices(geometry); - } +// } // Unsigned int indices are supported. No need to break into multiple geometries. return [geometry]; diff --git a/Specs/Core/GeometryPipelineSpec.js b/Specs/Core/GeometryPipelineSpec.js index 1f550219b1f0..e8856bfb50f6 100644 --- a/Specs/Core/GeometryPipelineSpec.js +++ b/Specs/Core/GeometryPipelineSpec.js @@ -110,6 +110,12 @@ defineSuite([ expect(v[11]).toEqual(2); }); + it('toWireframe throws without a geometry', function() { + expect(function() { + GeometryPipeline.toWireframe(undefined); + }).toThrow(); + }); + it('creates attribute indices', function() { var geometry = new Geometry({ attributes : { @@ -129,46 +135,13 @@ defineSuite([ expect(indices.position).not.toEqual(indices.color); }); - it('maps attribute indices to different names', function() { - var indices = { - positions : 0, - normals : 1, - colors : 2 - }; - - var mappedIndices = GeometryPipeline.mapAttributeIndices(indices, { - positions : 'position', - normals : 'normal', - colors : 'color' - }); - - expect(mappedIndices.position).toEqual(indices.positions); - expect(mappedIndices.normal).toEqual(indices.normals); - expect(mappedIndices.color).toEqual(indices.colors); - }); - - it('throws an exception when geometry properties have a different number of attributes', function() { + it('createAttributeIndices throws without a geometry', function() { expect(function() { - var geometry = new Geometry({ - attributes : { - attribute1 : new GeometryAttribute({ - componentDatatype : ComponentDatatype.FLOAT, - componentsPerAttribute : 1, - values : [0, 1, 2] - }), - attribute2 : new GeometryAttribute({ - componentDatatype : ComponentDatatype.FLOAT, - componentsPerAttribute : 3, - values : [0, 1, 2, 3, 4, 5] - }) - } - }); - - geometry = GeometryPipeline.reorderForPreVertexCache(geometry); + GeometryPipeline.createAttributeIndices(undefined); }).toThrow(); }); - it('can reorder all indices and attributes for the pre vertex cahce', function() { + it('reorderForPreVertexCache reorders all indices and attributes for the pre vertex cahce', function() { var geometry = new Geometry({ attributes : { weight : new GeometryAttribute({ @@ -228,29 +201,55 @@ defineSuite([ expect(geometry.attributes.positions.values[17]).toEqual(14); }); - it('can reorder indices for the post vertex cache', function() { + it('reorderForPreVertexCache throws without a geometry', function() { + expect(function() { + GeometryPipeline.reorderForPreVertexCache(undefined); + }).toThrow(); + }); + + it('reorderForPreVertexCache throws when attributes have a different number of attributes', function() { + expect(function() { + var geometry = new Geometry({ + attributes : { + attribute1 : new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 1, + values : [0, 1, 2] + }), + attribute2 : new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : [0, 1, 2, 3, 4, 5] + }) + } + }); + + geometry = GeometryPipeline.reorderForPreVertexCache(geometry); + }).toThrow(); + }); + + it('reorderForPostVertexCache reorders indices for the post vertex cache', function() { var geometry = new EllipsoidGeometry({ ellipsoid : new Ellipsoid(10.0, 10.0, 10.0), numberOfPartitions : 100 }); - var indices = geometry.indexList; - var numIndices = indices.length; - var maximumIndex = 0; - for ( var i = 0; i < numIndices; i++) { - if (indices[i] > maximumIndex) { - maximumIndex = indices[i]; - } - } - var ACMRbefore = Tipsify.calculateACMR({indices : indices, - maximumIndex : maximumIndex, - cacheSize : 24}); - expect(ACMRbefore).toBeGreaterThan(1.00); + var acmrBefore = Tipsify.calculateACMR({ + indices : geometry.indexList, + cacheSize : 24 + }); + expect(acmrBefore).toBeGreaterThan(1.0); geometry = GeometryPipeline.reorderForPostVertexCache(geometry); - indices = geometry.indexList; - var ACMRafter = Tipsify.calculateACMR({indices : indices, - maximumIndex : maximumIndex, - cacheSize : 24}); - expect(ACMRafter).toBeLessThan(0.70); + var acmrAfter = Tipsify.calculateACMR({ + indices : geometry.indexList, + cacheSize : 24 + }); + expect(acmrAfter).toBeLessThan(0.7); + }); + + it('reorderForPostVertexCache throws without a geometry', function() { + expect(function() { + GeometryPipeline.reorderForPostVertexCache(undefined); + }).toThrow(); }); it('fitToUnsignedShortIndices does not change geometry', function() { @@ -307,7 +306,7 @@ defineSuite([ expect(geometries[0].indexList).toEqual([0, 0, 0, 1, 1, 1, 0, 1, 0]); }); - it('fitToUnsignedShortIndices creates two geometries', function() { + it('fitToUnsignedShortIndices creates two triangle geometries', function() { var sixtyFourK = 64 * 1024; var positions = []; @@ -344,17 +343,93 @@ defineSuite([ expect(geometries[1].indexList.length).toEqual(3); }); - it('fitToUnsignedShortIndices throws without triangles', function() { + it('fitToUnsignedShortIndices creates two line geometries', function() { + var sixtyFourK = 64 * 1024; + + var positions = []; + for ( var i = 0; i < sixtyFourK + 2; ++i) { + positions.push(i, i, i); + } + + var indices = []; + for ( var j = sixtyFourK; j > 1; j -= 2) { + indices.push(j, j - 1); + } + indices.push(0, 1); + + var geometry = new Geometry({ + attributes : { + position : new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : positions + }) + }, + indexList : indices, + primitiveType : PrimitiveType.LINES + }); + + var geometries = GeometryPipeline.fitToUnsignedShortIndices(geometry); + + expect(geometries.length).toEqual(2); + + expect(geometries[0].attributes.position.values.length).toEqual(positions.length - 6); // Two vertices are not copied (0, 1) + expect(geometries[0].indexList.length).toEqual(indices.length - 2); // One line is not copied (0, 1) + + expect(geometries[1].attributes.position.values.length).toEqual(6); + expect(geometries[1].indexList.length).toEqual(2); + }); + + it('fitToUnsignedShortIndices creates two point geometries', function() { + var sixtyFourK = 64 * 1024; + + var positions = []; + var indices = []; + for ( var i = 0; i < sixtyFourK + 1; ++i) { + positions.push(i, i, i); + indices.push(i); + } + + var geometry = new Geometry({ + attributes : { + position : new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : positions + }) + }, + indexList : indices, + primitiveType : PrimitiveType.POINTS + }); + + var geometries = GeometryPipeline.fitToUnsignedShortIndices(geometry); + + expect(geometries.length).toEqual(2); + + expect(geometries[0].attributes.position.values.length).toEqual(positions.length - 3); // One vertex is not copied + expect(geometries[0].indexList.length).toEqual(indices.length - 1); // One point is not copied + + expect(geometries[1].attributes.position.values.length).toEqual(3); + expect(geometries[1].indexList.length).toEqual(1); + }); + + it('fitToUnsignedShortIndices throws without a geometry', function() { + expect(function() { + GeometryPipeline.fitToUnsignedShortIndices(undefined); + }).toThrow(); + }); + + it('fitToUnsignedShortIndices throws without triangles, lines, or points', function() { var geometry = new Geometry({ attributes : { time : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 1, - values : [10.0] + values : [10.0, 11.0, 12.0] }) }, - indexList : [0], - primitiveType : PrimitiveType.POINTS + indexList : [0, 1, 2], + primitiveType : PrimitiveType.TRIANGLE_STRIP }); expect(function() { @@ -417,7 +492,7 @@ defineSuite([ expect(geometry.attributes.position3D.values[5]).toEqual(p2.z); }); - it('GeometryPipeline.encodeAttribute encodes positions', function() { + it('encodeAttribute encodes positions', function() { var c = new Cartesian3(-10000000.0, 0.0, 10000000.0); var encoded = EncodedCartesian3.fromCartesian(c); @@ -443,25 +518,25 @@ defineSuite([ expect(geometry.attributes.position).not.toBeDefined(); }); - it('GeometryPipeline.encodeAttribute throws without a geometry', function() { + it('encodeAttribute throws without a geometry', function() { expect(function() { GeometryPipeline.encodeAttribute(undefined); }).toThrow(); }); - it('GeometryPipeline.encodeAttribute throws with geometry without attributes property', function() { + it('encodeAttribute throws with geometry without attributes property', function() { expect(function() { GeometryPipeline.encodeAttribute({}); }).toThrow(); }); - it('GeometryPipeline.encodeAttribute throws without attribute', function() { + it('encodeAttribute throws without attribute', function() { expect(function() { GeometryPipeline.encodeAttribute(new Geometry()); }).toThrow(); }); - it('GeometryPipeline.encodeAttribute throws without ComponentDatatype.FLOAT', function() { + it('encodeAttribute throws without ComponentDatatype.FLOAT', function() { expect(function() { var geometry = new Geometry({ attributes : new GeometryAttribute({ @@ -474,7 +549,7 @@ defineSuite([ }).toThrow(); }); - it('GeometryPipeline.combine combines one geometry', function() { + it('combine combines one geometry', function() { var instance = new GeometryInstance({ geometry : new Geometry({ attributes : new GeometryAttribute({ @@ -484,14 +559,14 @@ defineSuite([ values : [0.0, 0.0, 0.0] } }) - }), + }) }); var combined = GeometryPipeline.combine([instance]); expect(combined).toBe(instance.geometry); }); - it('GeometryPipeline.combine combines several geometries', function() { + it('combine combines several geometries', function() { var instance = new GeometryInstance({ geometry : new Geometry({ attributes : { @@ -557,31 +632,31 @@ defineSuite([ })); }); - it('GeometryPipeline.combine throws with instances', function() { + it('combine throws with instances', function() { expect(function() { GeometryPipeline.combine(); }).toThrow(); }); - it('GeometryPipeline.combine throws when instances.length is zero', function() { + it('combine throws when instances.length is zero', function() { expect(function() { GeometryPipeline.combine([]); }).toThrow(); }); - it('GeometryPipeline.computeNormal throws when geometry is undefined', function() { + it('computeNormal throws when geometry is undefined', function() { expect(function() { GeometryPipeline.computeNormal(); }).toThrow(); }); - it('GeometryPipeline.computeNormal throws when geometry.attributes.position is undefined', function() { + it('computeNormal throws when geometry.attributes.position is undefined', function() { expect(function() { GeometryPipeline.computeNormal(new Geometry()); }).toThrow(); }); - it('GeometryPipeline.computeNormal throws when geometry.attributes.position.values is undefined', function() { + it('computeNormal throws when geometry.attributes.position.values is undefined', function() { expect(function() { GeometryPipeline.computeNormal(new Geometry({ attributes: { @@ -591,7 +666,7 @@ defineSuite([ }).toThrow(); }); - it('GeometryPipeline.computeNormal throws when geometry.attributes.position.componentsPerAttribute is not 3', function() { + it('computeNormal throws when geometry.attributes.position.componentsPerAttribute is not 3', function() { expect(function() { GeometryPipeline.computeNormal(new Geometry({ attributes: { @@ -604,7 +679,7 @@ defineSuite([ }).toThrow(); }); - it('GeometryPipeline.computeNormal throws when geometry.attributes.position.values is not a multiple of 3', function() { + it('computeNormal throws when geometry.attributes.position.values is not a multiple of 3', function() { expect(function() { GeometryPipeline.computeNormal(new Geometry( { attributes: { @@ -617,7 +692,7 @@ defineSuite([ }).toThrow(); }); - it('GeometryPipeline.computeNormal does not compute normals when geometry.indexList is undefined', function() { + it('computeNormal does not compute normals when geometry.indexList is undefined', function() { var geometry = new Geometry({ attributes: { position: new GeometryAttribute({ @@ -632,7 +707,7 @@ defineSuite([ expect(typeof geometry.attributes.normal === 'undefined').toEqual(true); }); - it('GeometryPipeline.computeNormal does not compute normals when primitive type is not triangle', function() { + it('computeNormal does not compute normals when primitive type is not triangle', function() { var geometry = new Geometry({ attributes: { position: new GeometryAttribute({ @@ -650,7 +725,7 @@ defineSuite([ }); - it('GeometryPipeline.computeNormal computes normal for one triangle', function() { + it('computeNormal computes normal for one triangle', function() { var geometry = new Geometry({ attributes: { position: new GeometryAttribute({ @@ -668,7 +743,7 @@ defineSuite([ expect(geometry.attributes.normal.values).toEqual([0, 0, 1, 0, 0, 1, 0, 0, 1]); }); - it('GeometryPipeline.computeNormal computes normal for two triangles', function() { + it('computeNormal computes normal for two triangles', function() { var geometry = new Geometry({ attributes: { position: new GeometryAttribute({ @@ -690,7 +765,7 @@ defineSuite([ expect(geometry.attributes.normal.values.slice(9, 12)).toEqual([a.x, a.y, a.z]); }); - it('GeometryPipeline.computeNormal computes normal for six triangles', function() { + it('computeNormal computes normal for six triangles', function() { var geometry = new Geometry ({ attributes: { position: new GeometryAttribute({ @@ -718,13 +793,13 @@ defineSuite([ expect(geometry.attributes.normal.values.slice(18,21)).toEqual([0, 0, -1]); }); - it('GeometryPipeline.computeTangentAndBinormal throws when geometry is undefined', function() { + it('computeTangentAndBinormal throws when geometry is undefined', function() { expect(function() { GeometryPipeline.computeTangentAndBinormal(); }).toThrow(); }); - it('GeometryPipeline.computeTangentAndBinormal throws when geometry.attributes.position is undefined', function() { + it('computeTangentAndBinormal throws when geometry.attributes.position is undefined', function() { expect(function() { GeometryPipeline.computeTangentAndBinormal(new Geometry({ attributes: {} @@ -732,7 +807,7 @@ defineSuite([ }).toThrow(); }); - it('GeometryPipeline.computeTangentAndBinormal throws when geometry.attributes.position.values is undefined', function() { + it('computeTangentAndBinormal throws when geometry.attributes.position.values is undefined', function() { expect(function() { GeometryPipeline.computeTangentAndBinormal(new Geometry({ attributes: { @@ -742,7 +817,7 @@ defineSuite([ }).toThrow(); }); - it('GeometryPipeline.computeTangentAndBinormal throws when geometry.attributes.position.componentsPerAttribute is not 3', function() { + it('computeTangentAndBinormal throws when geometry.attributes.position.componentsPerAttribute is not 3', function() { expect(function() { GeometryPipeline.computeTangentAndBinormal(new Geometry({ attributes: { @@ -755,7 +830,7 @@ defineSuite([ }).toThrow(); }); - it('GeometryPipeline.computeTangentAndBinormal throws when geometry.attributes.position.values is not a multiple of 3', function() { + it('computeTangentAndBinormal throws when geometry.attributes.position.values is not a multiple of 3', function() { expect(function() { GeometryPipeline.computeTangentAndBinormal(new Geometry({ attributes: { @@ -768,7 +843,7 @@ defineSuite([ }).toThrow(); }); - it('GeometryPipeline.computeTangentAndBinormal throws when geometry.attributes.normal is undefined', function() { + it('computeTangentAndBinormal throws when geometry.attributes.normal is undefined', function() { expect(function() { GeometryPipeline.computeTangentAndBinormal(new Geometry({ attributes: { @@ -781,7 +856,7 @@ defineSuite([ }).toThrow(); }); - it('GeometryPipeline.computeTangentAndBinormal throws when geometry.attributes.normal.values is undefined', function() { + it('computeTangentAndBinormal throws when geometry.attributes.normal.values is undefined', function() { expect(function() { GeometryPipeline.computeTangentAndBinormal(new Geometry({ attributes: { @@ -795,7 +870,7 @@ defineSuite([ }).toThrow(); }); - it('GeometryPipeline.computeTangentAndBinormal throws when geometry.attributes.normal.componentsPerAttribute is not 3', function() { + it('computeTangentAndBinormal throws when geometry.attributes.normal.componentsPerAttribute is not 3', function() { expect(function() { GeometryPipeline.computeTangentAndBinormal(new Geometry({ attributes: { @@ -812,7 +887,7 @@ defineSuite([ }).toThrow(); }); - it('GeometryPipeline.computeTangentAndBinormal throws when geometry.attributes.normal.values is not a multiple of 3', function() { + it('computeTangentAndBinormal throws when geometry.attributes.normal.values is not a multiple of 3', function() { expect(function() { GeometryPipeline.computeTangentAndBinormal(new Geometry({ attributes: { @@ -829,7 +904,7 @@ defineSuite([ }).toThrow(); }); - it('GeometryPipeline.computeTangentAndBinormal throws when geometry.attributes.st is undefined', function() { + it('computeTangentAndBinormal throws when geometry.attributes.st is undefined', function() { expect(function() { GeometryPipeline.computeTangentAndBinormal(new Geometry( { attributes: { @@ -847,7 +922,7 @@ defineSuite([ }).toThrow(); }); - it('GeometryPipeline.computeTangentAndBinormal throws when geometry.attributes.normal.values is undefined', function() { + it('computeTangentAndBinormal throws when geometry.attributes.normal.values is undefined', function() { expect(function() { GeometryPipeline.computeTangentAndBinormal(new Geometry( { attributes: { @@ -865,7 +940,7 @@ defineSuite([ }).toThrow(); }); - it('GeometryPipeline.computeTangentAndBinormal throws when geometry.attributes.st.componentsPerAttribute is not 2', function() { + it('computeTangentAndBinormal throws when geometry.attributes.st.componentsPerAttribute is not 2', function() { expect(function() { GeometryPipeline.computeTangentAndBinormal(new Geometry( { attributes: { @@ -886,7 +961,7 @@ defineSuite([ }).toThrow(); }); - it('GeometryPipeline.computeTangentAndBinormal throws when geometry.attributes.st.values is not a multiple of 2', function() { + it('computeTangentAndBinormal throws when geometry.attributes.st.values is not a multiple of 2', function() { expect(function() { GeometryPipeline.computeTangentAndBinormal(new Geometry( { attributes: { @@ -907,7 +982,7 @@ defineSuite([ }).toThrow(); }); - it('GeometryPipeline.computeTangentAndBinormal does not compute tangent and binormals when geometry.indexList is undefined', function() { + it('computeTangentAndBinormal does not compute tangent and binormals when geometry.indexList is undefined', function() { var geometry = new Geometry({ attributes: { position: new GeometryAttribute({ @@ -932,7 +1007,7 @@ defineSuite([ expect(typeof geometry.attributes.binormal === 'undefined').toEqual(true); }); - it('GeometryPipeline.computeTangentAndBinormal does not compute tangent and binormals when primitive type is not triangle', function() { + it('computeTangentAndBinormal does not compute tangent and binormals when primitive type is not triangle', function() { var geometry = new Geometry({ attributes: { position: new GeometryAttribute({ @@ -960,7 +1035,7 @@ defineSuite([ expect(typeof geometry.attributes.binormal === 'undefined').toEqual(true); }); - it('GeometryPipeline.computeTangentAndBinormal computes tangent and binormal for one triangle', function() { + it('computeTangentAndBinormal computes tangent and binormal for one triangle', function() { var geometry = new Geometry({ attributes: { position: new GeometryAttribute({ @@ -983,7 +1058,7 @@ defineSuite([ expect(geometry.attributes.binormal.values).toEqual([0, 1, 0, 0, 1, 0, 0, 1, 0]); }); - it('GeometryPipeline.computeTangentAndBinormal computes tangent and binormal for two triangles', function() { + it('computeTangentAndBinormal computes tangent and binormal for two triangles', function() { var geometry = new Geometry({ attributes: { position: new GeometryAttribute({ From d5d62ba23bd1971720934e66235d1bb9a77ca0b3 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Tue, 11 Jun 2013 14:39:25 -0400 Subject: [PATCH 156/306] More GeometryPipeline improvements --- Source/Core/GeometryPipeline.js | 64 ++++++++++++++++++++++-------- Source/Scene/Primitive.js | 4 +- Specs/Core/GeometryPipelineSpec.js | 6 +++ 3 files changed, 55 insertions(+), 19 deletions(-) diff --git a/Source/Core/GeometryPipeline.js b/Source/Core/GeometryPipeline.js index 45846fc11054..f07da519855f 100644 --- a/Source/Core/GeometryPipeline.js +++ b/Source/Core/GeometryPipeline.js @@ -101,7 +101,7 @@ define([ * * @param {Geometry} geometry The geometry to modify, which is modified in place. * - * @returns The modified geometry argument, with its triangle indices converted to lines. + * @returns {Geometry} The modified geometry argument, with its triangle indices converted to lines. * * @exception {DeveloperError} geometry is required. * @@ -139,7 +139,7 @@ define([ * * @param {Geometry} geometry The geometry, which is not modified, to create the object for. * - * @returns An object with attribute name / index pairs. + * @returns {Object} An object with attribute name / index pairs. * * @exception {DeveloperError} geometry is required. * @@ -178,11 +178,11 @@ define([ * * @param {Geometry} geometry The geometry to modify, which is modified in place. * + * @returns {Geometry} The modified geometry argument, with its attributes and indices reordered for the GPU's pre-vertex-shader cache. + * * @exception {DeveloperError} geometry is required. * @exception {DeveloperError} Each attribute array in geometry.attributes must have the same number of attributes. * - * @returns The modified geometry argument, with its attributes and indices reordered for the GPU's pre-vertex-shader cache. - * * @see GeometryPipeline.reorderForPostVertexCache * * @example @@ -260,11 +260,11 @@ define([ * @param {Geometry} geometry The geometry to modify, which is modified in place. * @param {Number} [cacheCapacity=24] The number of vertices that can be held in the GPU's vertex cache. * + * @returns {Geometry} The modified geometry argument, with its indices reordered for the post-vertex-shader cache. + * * @exception {DeveloperError} geometry is required. * @exception {DeveloperError} cacheCapacity must be greater than two. * - * @returns The modified geometry argument, with its indices reordered for the post-vertex-shader cache. - * * @see GeometryPipeline.reorderForPreVertexCache * @see * Fast Triangle Reordering for Vertex Locality and Reduced Overdraw @@ -328,13 +328,23 @@ define([ } /** - * DOC_TBA. Old geometry is not guaranteed to be copied. - * + * Splits a geometry into multiple geometries - if necessary - to ensure that indices in the + * indexList fit into unsigned shorts. This is used to meet the WebGL requirements + * when {@link Context#getElementIndexUint} is false. + *

    * If the geometry does not have an indexList, this function has no effect. + *

    + * + * @param {Geometry} geometry The geometry to modify, which is modified in place if it needs to be split into multiple geometries. + * + * @returns {Array} An array of geometries, each with indices that fit into unsigned shorts. * * @exception {DeveloperError} geometry is required. * @exception {DeveloperError} geometry.primitiveType must equal to PrimitiveType.TRIANGLES, PrimitiveType.LINES, or PrimitiveType.POINTS * @exception {DeveloperError} All geometry attribute lists must have the same number of attributes. + * + * @example + * var geometries = GeometryPipeline.fitToUnsignedShortIndices(geometry); */ GeometryPipeline.fitToUnsignedShortIndices = function(geometry) { if (typeof geometry === 'undefined') { @@ -415,12 +425,32 @@ define([ return geometries; }; + var scratchCartesian = new Cartesian3(); + /** - * DOC_TBA + * Projects a geometry's 3D position attribute to 2D, replacing the position + * attribute with separate position3D and position2D attributes. + *

    + * If the geometry does not have a position, this function has no effect. + *

    + * + * @param {Geometry} geometry The geometry to modify, which is modified in place. + * @param {Object} [projection=new GeographicProjection()] The projection to use. + * + * @returns {Geometry} The modified geometry argument with position3D and position2D attributes. + * + * @exception {DeveloperError} geometry is required. + * + * @example + * geometry = GeometryPipeline.projectTo2D(geometry); */ GeometryPipeline.projectTo2D = function(geometry, projection) { - if (typeof geometry !== 'undefined' && typeof geometry.attributes.position !== 'undefined') { - projection = typeof projection !== 'undefined' ? projection : new GeographicProjection(); + if (typeof geometry === 'undefined') { + throw new DeveloperError('geometry is required.'); + } + + if (typeof geometry.attributes.position !== 'undefined') { + projection = (typeof projection !== 'undefined') ? projection : new GeographicProjection(); var ellipsoid = projection.getEllipsoid(); // Project original positions to 2D. @@ -428,7 +458,7 @@ define([ var projectedPositions = []; for ( var i = 0; i < wgs84Positions.length; i += 3) { - var lonLat = ellipsoid.cartesianToCartographic(new Cartesian3(wgs84Positions[i], wgs84Positions[i + 1], wgs84Positions[i + 2])); + var lonLat = ellipsoid.cartesianToCartographic(Cartesian3.fromArray(wgs84Positions, i, scratchCartesian)); var projectedLonLat = projection.project(lonLat); projectedPositions.push(projectedLonLat.x, projectedLonLat.y); } @@ -437,11 +467,11 @@ define([ geometry.attributes.position3D = geometry.attributes.position; // Replace original positions with 2D projected positions - geometry.attributes.position2D = { + geometry.attributes.position2D = new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 2, values : projectedPositions - }; + }); delete geometry.attributes.position; } @@ -465,7 +495,7 @@ define([ * @param {String} [attributeHighName='positionHigh'] The name of the attribute for the encoded high bits. * @param {String} [attributeLowName='positionLow'] The name of the attribute for the encoded low bits. * - * @returns The modified geometry argument, with its encoded attribute. + * @returns {Geometry} The modified geometry argument, with its encoded attribute. * * @exception {DeveloperError} geometry is required. * @exception {DeveloperError} geometry must have attribute matching the attributeName argument. @@ -803,7 +833,7 @@ define([ * @param {Geometry} geometry The geometry to modify, which is modified in place. * @param {Object} geometry.attributes.position * - * @returns The modified geometry argument. + * @returns {Geometry} The modified geometry argument. * * @exception {DeveloperError} geometry.attributes.position.values is required * @exception {DeveloperError} geometry.attributes.position.values.length must be a multiple of 3 @@ -949,7 +979,7 @@ define([ * @param {Object} geometry.attributes.normal The normals of the vertices * @param {Object} geometry.attributes.st The texture coordinates * - * @returns The modified geometry argument. + * @returns {Geometry} The modified geometry argument. * * @exception {DeveloperError} geometry.attributes.position.values is required * @exception {DeveloperError} geometry.attributes.position.values.length must be a multiple of 3 diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index 86adbefb4734..6849a3583498 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -316,10 +316,10 @@ define([ // Split position for GPU RTE GeometryPipeline.encodeAttribute(geometry, 'position', 'positionHigh', 'positionLow'); -// if (!context.getElementIndexUint()) { + if (!context.getElementIndexUint()) { // Break into multiple geometries to fit within unsigned short indices if needed return GeometryPipeline.fitToUnsignedShortIndices(geometry); -// } + } // Unsigned int indices are supported. No need to break into multiple geometries. return [geometry]; diff --git a/Specs/Core/GeometryPipelineSpec.js b/Specs/Core/GeometryPipelineSpec.js index e8856bfb50f6..87a6c888d23d 100644 --- a/Specs/Core/GeometryPipelineSpec.js +++ b/Specs/Core/GeometryPipelineSpec.js @@ -492,6 +492,12 @@ defineSuite([ expect(geometry.attributes.position3D.values[5]).toEqual(p2.z); }); + it('projectTo2D throws without a geometry', function() { + expect(function() { + GeometryPipeline.projectTo2D(undefined); + }).toThrow(); + }); + it('encodeAttribute encodes positions', function() { var c = new Cartesian3(-10000000.0, 0.0, 10000000.0); var encoded = EncodedCartesian3.fromCartesian(c); From 466ab7838c313469281bf1e61548a3d3cb047f60 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Tue, 11 Jun 2013 16:27:44 -0400 Subject: [PATCH 157/306] Start modifying geometry to use typed arrays. --- Source/Core/BoxGeometry.js | 484 ++++++++++++++++--------------- Source/Core/EllipseGeometry.js | 17 +- Source/Core/EllipsoidGeometry.js | 10 +- Source/Core/ExtentGeometry.js | 13 +- Source/Core/GeometryPipeline.js | 99 ++++--- Source/Core/PolygonGeometry.js | 8 +- Source/Core/WallGeometry.js | 12 +- 7 files changed, 345 insertions(+), 298 deletions(-) diff --git a/Source/Core/BoxGeometry.js b/Source/Core/BoxGeometry.js index f86be1e2d839..6271fd35ae30 100644 --- a/Source/Core/BoxGeometry.js +++ b/Source/Core/BoxGeometry.js @@ -66,289 +66,311 @@ define([ var attributes = {}; var indexList; + var positions; if (vertexFormat !== VertexFormat.POSITION_ONLY) { - if (vertexFormat.position) { // 8 corner points. Duplicated 3 times each for each incident edge/face. + positions = new Float64Array(6 * 4 * 3); + + // +z face + positions[0] = min.x; positions[1] = min.y; positions[2] = max.z; + positions[3] = max.x; positions[4] = min.y; positions[5] = max.z; + positions[6] = max.x; positions[7] = max.y; positions[8] = max.z; + positions[9] = min.x; positions[10] = max.y; positions[11] = max.z; + + // -z face + positions[12] = min.x; positions[13] = min.y; positions[14] = min.z; + positions[15] = max.x; positions[16] = min.y; positions[17] = min.z; + positions[18] = max.x; positions[19] = max.y; positions[20] = min.z; + positions[21] = min.x; positions[22] = max.y; positions[23] = min.z; + + // +x face + positions[24] = max.x; positions[25] = min.y; positions[26] = min.z; + positions[27] = max.x; positions[28] = max.y; positions[29] = min.z; + positions[30] = max.x; positions[31] = max.y; positions[32] = max.z; + positions[33] = max.x; positions[34] = min.y; positions[35] = max.z; + + // -x face + positions[36] = min.x; positions[37] = min.y; positions[38] = min.z; + positions[39] = min.x; positions[40] = max.y; positions[41] = min.z; + positions[42] = min.x; positions[43] = max.y; positions[44] = max.z; + positions[45] = min.x; positions[46] = min.y; positions[47] = max.z; + + // +y face + positions[48] = min.x; positions[49] = max.y; positions[50] = min.z; + positions[51] = max.x; positions[52] = max.y; positions[53] = min.z; + positions[54] = max.x; positions[55] = max.y; positions[56] = max.z; + positions[57] = min.x; positions[58] = max.y; positions[59] = max.z; + + // -y face + positions[60] = min.x; positions[61] = min.y; positions[62] = min.z; + positions[63] = max.x; positions[64] = min.y; positions[65] = min.z; + positions[66] = max.x; positions[67] = min.y; positions[68] = max.z; + positions[69] = min.x; positions[70] = min.y; positions[71] = max.z; + attributes.position = new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 3, - values : [ - // +z face - min.x, min.y, max.z, - max.x, min.y, max.z, - max.x, max.y, max.z, - min.x, max.y, max.z, - - // -z face - min.x, min.y, min.z, - max.x, min.y, min.z, - max.x, max.y, min.z, - min.x, max.y, min.z, - - // +x face - max.x, min.y, min.z, - max.x, max.y, min.z, - max.x, max.y, max.z, - max.x, min.y, max.z, - - // -x face - min.x, min.y, min.z, - min.x, max.y, min.z, - min.x, max.y, max.z, - min.x, min.y, max.z, - - // +y face - min.x, max.y, min.z, - max.x, max.y, min.z, - max.x, max.y, max.z, - min.x, max.y, max.z, - - // -y face - min.x, min.y, min.z, - max.x, min.y, min.z, - max.x, min.y, max.z, - min.x, min.y, max.z - ] + values : positions }); } if (vertexFormat.normal) { + var normals = new Float32Array(6 * 4 * 3); + + // +z face + normals[0] = 0.0; normals[1] = 0.0; normals[2] = 1.0; + normals[3] = 0.0; normals[4] = 0.0; normals[5] = 1.0; + normals[6] = 0.0; normals[7] = 0.0; normals[8] = 1.0; + normals[9] = 0.0; normals[10] = 0.0; normals[11] = 1.0; + + // -z face + normals[12] = 0.0; normals[13] = 0.0; normals[14] = -1.0; + normals[15] = 0.0; normals[16] = 0.0; normals[17] = -1.0; + normals[18] = 0.0; normals[19] = 0.0; normals[20] = -1.0; + normals[21] = 0.0; normals[22] = 0.0; normals[23] = -1.0; + + // +x face + normals[24] = 1.0; normals[25] = 0.0; normals[26] = 0.0; + normals[27] = 1.0; normals[28] = 0.0; normals[29] = 0.0; + normals[30] = 1.0; normals[31] = 0.0; normals[32] = 0.0; + normals[33] = 1.0; normals[34] = 0.0; normals[35] = 0.0; + + // -x face + normals[36] = -1.0; normals[37] = 0.0; normals[38] = 0.0; + normals[39] = -1.0; normals[40] = 0.0; normals[41] = 0.0; + normals[42] = -1.0; normals[43] = 0.0; normals[44] = 0.0; + normals[45] = -1.0; normals[46] = 0.0; normals[47] = 0.0; + + // +y face + normals[48] = 0.0; normals[49] = 1.0; normals[50] = 0.0; + normals[51] = 0.0; normals[52] = 1.0; normals[53] = 0.0; + normals[54] = 0.0; normals[55] = 1.0; normals[56] = 0.0; + normals[57] = 0.0; normals[58] = 1.0; normals[59] = 0.0; + + // -y face + normals[60] = 0.0; normals[61] = -1.0; normals[62] = 0.0; + normals[63] = 0.0; normals[64] = -1.0; normals[65] = 0.0; + normals[66] = 0.0; normals[67] = -1.0; normals[68] = 0.0; + normals[69] = 0.0; normals[70] = -1.0; normals[71] = 0.0; + attributes.normal = new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 3, - values : [ - // +z face - 0.0, 0.0, 1.0, - 0.0, 0.0, 1.0, - 0.0, 0.0, 1.0, - 0.0, 0.0, 1.0, - - // -z face - 0.0, 0.0, -1.0, - 0.0, 0.0, -1.0, - 0.0, 0.0, -1.0, - 0.0, 0.0, -1.0, - - // +x face - 1.0, 0.0, 0.0, - 1.0, 0.0, 0.0, - 1.0, 0.0, 0.0, - 1.0, 0.0, 0.0, - - // -x face - -1.0, 0.0, 0.0, - -1.0, 0.0, 0.0, - -1.0, 0.0, 0.0, - -1.0, 0.0, 0.0, - - // +y face - 0.0, 1.0, 0.0, - 0.0, 1.0, 0.0, - 0.0, 1.0, 0.0, - 0.0, 1.0, 0.0, - - // -y face - 0.0, -1.0, 0.0, - 0.0, -1.0, 0.0, - 0.0, -1.0, 0.0, - 0.0, -1.0, 0.0 - ] + values : normals }); } if (vertexFormat.st) { + var texCoords = new Float32Array(6 * 4 * 2); + + // +z face + texCoords[0] = 0.0; texCoords[1] = 0.0; + texCoords[2] = 1.0; texCoords[3] = 0.0; + texCoords[4] = 1.0; texCoords[5] = 1.0; + texCoords[6] = 0.0; texCoords[7] = 1.0; + + // -z face + texCoords[8] = 1.0; texCoords[9] = 0.0; + texCoords[10] = 0.0; texCoords[11] = 0.0; + texCoords[12] = 0.0; texCoords[13] = 1.0; + texCoords[14] = 1.0; texCoords[15] = 1.0; + + //+x face + texCoords[16] = 0.0; texCoords[17] = 0.0; + texCoords[18] = 1.0; texCoords[19] = 0.0; + texCoords[20] = 1.0; texCoords[21] = 1.0; + texCoords[22] = 0.0; texCoords[23] = 1.0; + + // -x face + texCoords[24] = 1.0; texCoords[25] = 0.0; + texCoords[26] = 0.0; texCoords[27] = 0.0; + texCoords[28] = 0.0; texCoords[29] = 1.0; + texCoords[30] = 1.0; texCoords[31] = 1.0; + + // +y face + texCoords[32] = 1.0; texCoords[33] = 0.0; + texCoords[34] = 0.0; texCoords[35] = 0.0; + texCoords[36] = 0.0; texCoords[37] = 1.0; + texCoords[38] = 1.0; texCoords[39] = 1.0; + + // -y face + texCoords[40] = 0.0; texCoords[41] = 0.0; + texCoords[42] = 1.0; texCoords[43] = 0.0; + texCoords[44] = 1.0; texCoords[45] = 1.0; + texCoords[46] = 0.0; texCoords[47] = 1.0; + attributes.st = new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 2, - values : [ - // +z face - 0.0, 0.0, - 1.0, 0.0, - 1.0, 1.0, - 0.0, 1.0, - - // -z face - 1.0, 0.0, - 0.0, 0.0, - 0.0, 1.0, - 1.0, 1.0, - - // +x face - 0.0, 0.0, - 1.0, 0.0, - 1.0, 1.0, - 0.0, 1.0, - - // -x face - 1.0, 0.0, - 0.0, 0.0, - 0.0, 1.0, - 1.0, 1.0, - - // +y face - 1.0, 0.0, - 0.0, 0.0, - 0.0, 1.0, - 1.0, 1.0, - - // -y face - 0.0, 0.0, - 1.0, 0.0, - 1.0, 1.0, - 0.0, 1.0 - ] + values : texCoords }); } if (vertexFormat.tangent) { + var tangents = new Float32Array(6 * 4 * 3); + + // +z face + tangents[0] = 1.0; tangents[1] = 0.0; tangents[2] = 0.0; + tangents[3] = 1.0; tangents[4] = 0.0; tangents[5] = 0.0; + tangents[6] = 1.0; tangents[7] = 0.0; tangents[8] = 0.0; + tangents[9] = 1.0; tangents[10] = 0.0; tangents[11] = 0.0; + + // -z face + tangents[12] = -1.0; tangents[13] = 0.0; tangents[14] = 0.0; + tangents[15] = -1.0; tangents[16] = 0.0; tangents[17] = 0.0; + tangents[18] = -1.0; tangents[19] = 0.0; tangents[20] = 0.0; + tangents[21] = -1.0; tangents[22] = 0.0; tangents[23] = 0.0; + + // +x face + tangents[24] = 0.0; tangents[25] = 1.0; tangents[26] = 0.0; + tangents[27] = 0.0; tangents[28] = 1.0; tangents[29] = 0.0; + tangents[30] = 0.0; tangents[31] = 1.0; tangents[32] = 0.0; + tangents[33] = 0.0; tangents[34] = 1.0; tangents[35] = 0.0; + + // -x face + tangents[36] = 0.0; tangents[37] = -1.0; tangents[38] = 0.0; + tangents[39] = 0.0; tangents[40] = -1.0; tangents[41] = 0.0; + tangents[42] = 0.0; tangents[43] = -1.0; tangents[44] = 0.0; + tangents[45] = 0.0; tangents[46] = -1.0; tangents[47] = 0.0; + + // +y face + tangents[48] = -1.0; tangents[49] = 0.0; tangents[50] = 0.0; + tangents[51] = -1.0; tangents[52] = 0.0; tangents[53] = 0.0; + tangents[54] = -1.0; tangents[55] = 0.0; tangents[56] = 0.0; + tangents[57] = -1.0; tangents[58] = 0.0; tangents[59] = 0.0; + + // -y face + tangents[60] = 1.0; tangents[61] = 0.0; tangents[62] = 0.0; + tangents[63] = 1.0; tangents[64] = 0.0; tangents[65] = 0.0; + tangents[66] = 1.0; tangents[67] = 0.0; tangents[68] = 0.0; + tangents[69] = 1.0; tangents[70] = 0.0; tangents[71] = 0.0; + attributes.tangent = new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 3, - values : [ - // +z face - 1.0, 0.0, 0.0, - 1.0, 0.0, 0.0, - 1.0, 0.0, 0.0, - 1.0, 0.0, 0.0, - - // -z face - -1.0, 0.0, 0.0, - -1.0, 0.0, 0.0, - -1.0, 0.0, 0.0, - -1.0, 0.0, 0.0, - - // +x face - 0.0, 1.0, 0.0, - 0.0, 1.0, 0.0, - 0.0, 1.0, 0.0, - 0.0, 1.0, 0.0, - - // -x face - 0.0, -1.0, 0.0, - 0.0, -1.0, 0.0, - 0.0, -1.0, 0.0, - 0.0, -1.0, 0.0, - - // +y face - -1.0, 0.0, 0.0, - -1.0, 0.0, 0.0, - -1.0, 0.0, 0.0, - -1.0, 0.0, 0.0, - - // -y face - 1.0, 0.0, 0.0, - 1.0, 0.0, 0.0, - 1.0, 0.0, 0.0, - 1.0, 0.0, 0.0 - ] + values : tangents }); } if (vertexFormat.binormal) { - attributes.binormal = new GeometryAttribute({ - componentDatatype : ComponentDatatype.FLOAT, - componentsPerAttribute : 3, - values : [ - // +z face - 0.0, 1.0, 0.0, - 0.0, 1.0, 0.0, - 0.0, 1.0, 0.0, - 0.0, 1.0, 0.0, - - // -z face - 0.0, 1.0, 0.0, - 0.0, 1.0, 0.0, - 0.0, 1.0, 0.0, - 0.0, 1.0, 0.0, - - // +x face - 0.0, 0.0, 1.0, - 0.0, 0.0, 1.0, - 0.0, 0.0, 1.0, - 0.0, 0.0, 1.0, - - // -x face - 0.0, 0.0, 1.0, - 0.0, 0.0, 1.0, - 0.0, 0.0, 1.0, - 0.0, 0.0, 1.0, - - // +y face - 0.0, 0.0, 1.0, - 0.0, 0.0, 1.0, - 0.0, 0.0, 1.0, - 0.0, 0.0, 1.0, - - // -y face - 0.0, 0.0, 1.0, - 0.0, 0.0, 1.0, - 0.0, 0.0, 1.0, - 0.0, 0.0, 1.0 - ] - }); - } + var binormals = new Float32Array(6 * 4 * 3); - // 12 triangles: 6 faces, 2 triangles each. - indexList = [ // +z face - 0, 1, 2, - 0, 2, 3, + binormals[0] = 0.0; binormals[1] = 1.0; binormals[2] = 0.0; + binormals[3] = 0.0; binormals[4] = 1.0; binormals[5] = 0.0; + binormals[6] = 0.0; binormals[7] = 1.0; binormals[8] = 0.0; + binormals[9] = 0.0; binormals[10] = 1.0; binormals[11] = 0.0; // -z face - 4 + 2, 4 + 1, 4 + 0, - 4 + 3, 4 + 2, 4 + 0, + binormals[12] = 0.0; binormals[13] = 1.0; binormals[14] = 0.0; + binormals[15] = 0.0; binormals[16] = 1.0; binormals[17] = 0.0; + binormals[18] = 0.0; binormals[19] = 1.0; binormals[20] = 0.0; + binormals[21] = 0.0; binormals[22] = 1.0; binormals[23] = 0.0; // +x face - 8 + 0, 8 + 1, 8 + 2, - 8 + 0, 8 + 2, 8 + 3, + binormals[24] = 0.0; binormals[25] = 0.0; binormals[26] = 1.0; + binormals[27] = 0.0; binormals[28] = 0.0; binormals[29] = 1.0; + binormals[30] = 0.0; binormals[31] = 0.0; binormals[32] = 1.0; + binormals[33] = 0.0; binormals[34] = 0.0; binormals[35] = 1.0; // -x face - 12 + 2, 12 + 1, 12 + 0, - 12 + 3, 12 + 2, 12 + 0, + binormals[36] = 0.0; binormals[37] = 0.0; binormals[38] = 1.0; + binormals[39] = 0.0; binormals[40] = 0.0; binormals[41] = 1.0; + binormals[42] = 0.0; binormals[43] = 0.0; binormals[44] = 1.0; + binormals[45] = 0.0; binormals[46] = 0.0; binormals[47] = 1.0; // +y face - 16 + 2, 16 + 1, 16 + 0, - 16 + 3, 16 + 2, 16 + 0, + binormals[48] = 0.0; binormals[49] = 0.0; binormals[50] = 1.0; + binormals[51] = 0.0; binormals[52] = 0.0; binormals[53] = 1.0; + binormals[54] = 0.0; binormals[55] = 0.0; binormals[56] = 1.0; + binormals[57] = 0.0; binormals[58] = 0.0; binormals[59] = 1.0; // -y face - 20 + 0, 20 + 1, 20 + 2, - 20 + 0, 20 + 2, 20 + 3 - ]; + binormals[60] = 0.0; binormals[61] = 0.0; binormals[62] = 1.0; + binormals[63] = 0.0; binormals[64] = 0.0; binormals[65] = 1.0; + binormals[66] = 0.0; binormals[67] = 0.0; binormals[68] = 1.0; + binormals[69] = 0.0; binormals[70] = 0.0; binormals[71] = 1.0; + + attributes.binormal = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : binormals + }); + } + + // 12 triangles: 6 faces, 2 triangles each. + indexList = new Uint32Array(6 * 2 * 3); + + // +z face + indexList[0] = 0; indexList[1] = 1; indexList[2] = 2; + indexList[3] = 0; indexList[4] = 2; indexList[5] = 3; + + // -z face + indexList[6] = 4 + 2; indexList[7] = 4 + 1; indexList[8] = 4 + 0; + indexList[9] = 4 + 3; indexList[10] = 4 + 2; indexList[11] = 4 + 0; + + // +x face + indexList[12] = 8 + 0; indexList[13] = 8 + 1; indexList[14] = 8 + 2; + indexList[15] = 8 + 0; indexList[16] = 8 + 2; indexList[17] = 8 + 3; + + // -x face + indexList[18] = 12 + 2; indexList[19] = 12 + 1; indexList[20] = 12 + 0; + indexList[21] = 12 + 3; indexList[22] = 12 + 2; indexList[23] = 12 + 0; + + // +y face + indexList[24] = 16 + 2; indexList[25] = 16 + 1; indexList[26] = 16 + 0; + indexList[27] = 16 + 3; indexList[28] = 16 + 2; indexList[29] = 16 + 0; + + // -y face + indexList[30] = 20 + 0; indexList[31] = 20 + 1; indexList[32] = 20 + 2; + indexList[33] = 20 + 0; indexList[34] = 20 + 2; indexList[35] = 20 + 3; } else { // Positions only - no need to duplicate corner points + positions = new Float64Array(8 * 3); + + positions[0] = min.x; positions[1] = min.y; positions[2] = min.z; + positions[3] = max.x; positions[4] = min.y; positions[5] = min.z; + positions[6] = max.x; positions[7] = max.y; positions[8] = min.z; + positions[9] = min.x; positions[10] = max.y; positions[11] = min.z; + positions[12] = min.x; positions[13] = min.y; positions[14] = max.z; + positions[15] = max.x; positions[16] = min.y; positions[17] = max.z; + positions[18] = max.x; positions[19] = max.y; positions[20] = max.z; + positions[21] = min.x; positions[22] = max.y; positions[23] = max.z; + attributes.position = new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 3, - values : [ - // 8 corner points. - min.x, min.y, min.z, - max.x, min.y, min.z, - max.x, max.y, min.z, - min.x, max.y, min.z, - min.x, min.y, max.z, - max.x, min.y, max.z, - max.x, max.y, max.z, - min.x, max.y, max.z - ] + values : positions }); // 12 triangles: 6 faces, 2 triangles each. - indexList = [ - 4, 5, 6, // plane z = corner.Z - 4, 6, 7, - 1, 0, 3, // plane z = -corner.Z - 1, 3, 2, - 1, 6, 5, // plane x = corner.X - 1, 2, 6, - 2, 3, 7, // plane y = corner.Y - 2, 7, 6, - 3, 0, 4, // plane x = -corner.X - 3, 4, 7, - 0, 1, 5, // plane y = -corner.Y - 0, 5, 4 - ]; + indexList = new Uint32Array(6 * 2 * 3); + + // plane z = corner.Z + indexList[0] = 4; indexList[1] = 5; indexList[2] = 6; + indexList[3] = 4; indexList[4] = 6; indexList[5] = 7; + + // plane z = -corner.Z + indexList[6] = 1; indexList[7] = 0; indexList[8] = 3; + indexList[9] = 1; indexList[10] = 3; indexList[11] = 2; + + // plane x = corner.X + indexList[12] = 1; indexList[13] = 6; indexList[14] = 5; + indexList[15] = 1; indexList[16] = 2; indexList[17] = 6; + + // plane y = corner.Y + indexList[18] = 2; indexList[19] = 3; indexList[20] = 7; + indexList[21] = 2; indexList[22] = 7; indexList[23] = 6; + + // plane x = -corner.X + indexList[24] = 3; indexList[25] = 0; indexList[26] = 4; + indexList[27] = 3; indexList[28] = 4; indexList[29] = 7; + + // plane y = -corner.Y + indexList[30] = 0; indexList[31] = 1; indexList[32] = 5; + indexList[33] = 0; indexList[34] = 5; indexList[35] = 4; } /** diff --git a/Source/Core/EllipseGeometry.js b/Source/Core/EllipseGeometry.js index 8c0d31c79d0c..b0e180a44089 100644 --- a/Source/Core/EllipseGeometry.js +++ b/Source/Core/EllipseGeometry.js @@ -236,13 +236,17 @@ define([ } // The original length may have been an over-estimate - positions.length = positionIndex; - size = positions.length / 3; + if (positions.length !== positionIndex) { + size = positionIndex / 3; + positions.length = positionIndex; + } + + positions = new Float64Array(positions); - var textureCoordinates = (vertexFormat.st) ? new Array(size * 2) : undefined; - var normals = (vertexFormat.normal) ? new Array(size * 3) : undefined; - var tangents = (vertexFormat.tangent) ? new Array(size * 3) : undefined; - var binormals = (vertexFormat.binormal) ? new Array(size * 3) : undefined; + var textureCoordinates = (vertexFormat.st) ? new Float32Array(size * 2) : undefined; + var normals = (vertexFormat.normal) ? new Float32Array(size * 3) : undefined; + var tangents = (vertexFormat.tangent) ? new Float32Array(size * 3) : undefined; + var binormals = (vertexFormat.binormal) ? new Float32Array(size * 3) : undefined; var textureCoordIndex = 0; @@ -420,6 +424,7 @@ define([ } indices.length = indicesIndex; + indices = new Uint32Array(indices); /** * An object containing {@link GeometryAttribute} properties named after each of the diff --git a/Source/Core/EllipsoidGeometry.js b/Source/Core/EllipsoidGeometry.js index a08180425f3b..45e680afa72d 100644 --- a/Source/Core/EllipsoidGeometry.js +++ b/Source/Core/EllipsoidGeometry.js @@ -213,7 +213,7 @@ define([ if (vertexFormat.position) { // Expand cube into ellipsoid and flatten values var radii = ellipsoid.getRadii(); - var flattenedPositions = new Array(length * 3); + var flattenedPositions = new Float64Array(length * 3); for (i = j = 0; i < length; ++i) { var item = positions[i]; @@ -233,7 +233,7 @@ define([ } if (vertexFormat.st) { - var texCoords = new Array(length * 2); + var texCoords = new Float32Array(length * 2); var oneOverRadii = ellipsoid.getOneOverRadii(); for (i = j = 0; i < length; ++i) { @@ -252,9 +252,9 @@ define([ } if (vertexFormat.normal || vertexFormat.tangent || vertexFormat.binormal) { - var normals = (vertexFormat.normal) ? new Array(length * 3) : undefined; - var tangents = (vertexFormat.tangent) ? new Array(length * 3) : undefined; - var binormals = (vertexFormat.binormal) ? new Array(length * 3) : undefined; + var normals = (vertexFormat.normal) ? new Float32Array(length * 3) : undefined; + var tangents = (vertexFormat.tangent) ? new Float32Array(length * 3) : undefined; + var binormals = (vertexFormat.binormal) ? new Float32Array(length * 3) : undefined; for (i = j = 0; i < length; ++i, j += 3) { ellipsoid.geodeticSurfaceNormal(positions[i], normal); diff --git a/Source/Core/ExtentGeometry.js b/Source/Core/ExtentGeometry.js index 0650fdbc6c81..378a23a80e5c 100644 --- a/Source/Core/ExtentGeometry.js +++ b/Source/Core/ExtentGeometry.js @@ -160,11 +160,11 @@ define([ var binormalIndex = 0; var size = width * height; - var positions = (vertexFormat.position) ? new Array(size * 3) : undefined; - var textureCoordinates = (vertexFormat.st) ? new Array(size * 2) : undefined; - var normals = (vertexFormat.normal) ? new Array(size * 3) : undefined; - var tangents = (vertexFormat.tangent) ? new Array(size * 3) : undefined; - var binormals = (vertexFormat.binormal) ? new Array(size * 3) : undefined; + var positions = (vertexFormat.position) ? new Float64Array(size * 3) : undefined; + var textureCoordinates = (vertexFormat.st) ? new Float32Array(size * 2) : undefined; + var normals = (vertexFormat.normal) ? new Float32Array(size * 3) : undefined; + var tangents = (vertexFormat.tangent) ? new Float32Array(size * 3) : undefined; + var binormals = (vertexFormat.binormal) ? new Float32Array(size * 3) : undefined; for ( var row = 0; row < height; ++row) { for ( var col = 0; col < width; ++col) { @@ -231,7 +231,8 @@ define([ } } - var indices = []; + var indicesSize = 6 * (width - 1) * (height - 1); + var indices = new Uint32Array(indicesSize); var index = 0; var indicesIndex = 0; for ( var i = 0; i < height - 1; ++i) { diff --git a/Source/Core/GeometryPipeline.js b/Source/Core/GeometryPipeline.js index a634ba29a864..4475e1fa7068 100644 --- a/Source/Core/GeometryPipeline.js +++ b/Source/Core/GeometryPipeline.js @@ -4,6 +4,7 @@ define([ './DeveloperError', './Cartesian3', './Cartesian2', + './Cartographic', './EncodedCartesian3', './Matrix3', './Matrix4', @@ -13,12 +14,13 @@ define([ './Tipsify', './BoundingSphere', './Geometry', - './GeometryAttribute', + './GeometryAttribute' ], function( defaultValue, DeveloperError, Cartesian3, Cartesian2, + Cartographic, EncodedCartesian3, Matrix3, Matrix4, @@ -295,7 +297,7 @@ define([ return geometry; }; - GeometryPipeline._copyAttributesDescriptions = function(attributes) { + function copyAttributesDescriptions(attributes) { var newAttributes = {}; for ( var attribute in attributes) { @@ -311,7 +313,7 @@ define([ } return newAttributes; - }; + } function copyVertex(destinationAttributes, sourceAttributes, index) { for ( var attribute in sourceAttributes) { @@ -348,7 +350,7 @@ define([ var oldToNewIndex = []; var newIndices = []; var currentIndex = 0; - var newAttributes = GeometryPipeline._copyAttributesDescriptions(geometry.attributes); + var newAttributes = copyAttributesDescriptions(geometry.attributes); var originalIndices = geometry.indexList; var numberOfIndices = originalIndices.length; @@ -399,7 +401,7 @@ define([ oldToNewIndex = []; newIndices = []; currentIndex = 0; - newAttributes = GeometryPipeline._copyAttributesDescriptions(geometry.attributes); + newAttributes = copyAttributesDescriptions(geometry.attributes); } } @@ -419,6 +421,9 @@ define([ return geometries; }; + var scratchProjectTo2DCartesian3 = new Cartesian3(); + var scratchProjectTo2DCartographic = new Cartographic(); + /** * DOC_TBA */ @@ -429,12 +434,16 @@ define([ // Project original positions to 2D. var wgs84Positions = geometry.attributes.position.values; - var projectedPositions = []; + var projectedPositions = new Array(2 * wgs84Positions.length / 3); // TODO: Float64Array? + var index = 0; for ( var i = 0; i < wgs84Positions.length; i += 3) { - var lonLat = ellipsoid.cartesianToCartographic(new Cartesian3(wgs84Positions[i], wgs84Positions[i + 1], wgs84Positions[i + 2])); - var projectedLonLat = projection.project(lonLat); - projectedPositions.push(projectedLonLat.x, projectedLonLat.y); + var position = Cartesian3.fromArray(wgs84Positions, i, scratchProjectTo2DCartesian3); + var lonLat = ellipsoid.cartesianToCartographic(position, scratchProjectTo2DCartographic); + var projectedLonLat = projection.project(lonLat, scratchProjectTo2DCartesian3); + + projectedPositions[index++] = projectedLonLat.x; + projectedPositions[index++] = projectedLonLat.y; } // Rename original positions to WGS84 Positions. @@ -501,8 +510,8 @@ define([ var values = attribute.values; var length = values.length; - var highValues = new Array(length); - var lowValues = new Array(length); + var highValues = new Float32Array(length); + var lowValues = new Float32Array(length); for (var i = 0; i < length; ++i) { EncodedCartesian3.encode(values[i], encodedResult); @@ -510,14 +519,17 @@ define([ lowValues[i] = encodedResult.low; } + var componentDatatype = attribute.componentDatatype; + var componentsPerAttribute = attribute.componentsPerAttribute; + geometry.attributes[attributeHighName] = new GeometryAttribute({ - componentDatatype : attribute.componentDatatype, - componentsPerAttribute : attribute.componentsPerAttribute, + componentDatatype : componentDatatype, + componentsPerAttribute : componentsPerAttribute, values : highValues }); geometry.attributes[attributeLowName] = new GeometryAttribute({ - componentDatatype : attribute.componentDatatype, - componentsPerAttribute : attribute.componentsPerAttribute, + componentDatatype : componentDatatype, + componentsPerAttribute : componentsPerAttribute, values : lowValues }); delete geometry.attributes[attributeName]; @@ -555,6 +567,9 @@ define([ } } + var inverseTranspose = new Matrix4(); + var normalMatrix = new Matrix3(); + /** * DOC_TBA * @@ -581,8 +596,6 @@ define([ (typeof attributes.binormal !== 'undefined') || (typeof attributes.tangent !== 'undefined')) { - var inverseTranspose = new Matrix4(); - var normalMatrix = new Matrix3(); Matrix4.inverse(modelMatrix, inverseTranspose); Matrix4.transpose(inverseTranspose, inverseTranspose); Matrix4.getRotation(inverseTranspose, normalMatrix); @@ -639,7 +652,6 @@ define([ componentDatatype : attribute.componentDatatype, componentsPerAttribute : attribute.componentsPerAttribute, normalize : attribute.normalize, -// TODO: or new Array() values : attribute.componentDatatype.createTypedArray(numberOfComponents) }); } @@ -728,7 +740,6 @@ define([ if (numberOfIndices.hasOwnProperty(name)) { var num = numberOfIndices[name]; -// TODO: or new Array() if (num < 60 * 1024) { values = new Uint16Array(num); } else { @@ -820,14 +831,17 @@ define([ if (typeof geometry === 'undefined') { throw new DeveloperError('geometry is required.'); } + var attributes = geometry.attributes; if (typeof attributes.position === 'undefined' || typeof attributes.position.values === 'undefined') { throw new DeveloperError('geometry.attributes.position.values is required'); } + var vertices = geometry.attributes.position.values; if (geometry.attributes.position.componentsPerAttribute !== 3 || vertices.length % 3 !== 0) { throw new DeveloperError('geometry.attributes.position.values.length must be a multiple of 3'); } + var indices = geometry.indexList; if (typeof indices === 'undefined') { return geometry; @@ -912,7 +926,7 @@ define([ geometry.attributes.normal = new GeometryAttribute({ componentDatatype: ComponentDatatype.FLOAT, componentsPerAttribute: 3, - values: new Array(numVertices * 3) + values: new Float32Array(numVertices * 3) }); } var normalValues = geometry.attributes.normal.values; @@ -969,24 +983,30 @@ define([ if (typeof geometry === 'undefined') { throw new DeveloperError('geometry is required.'); } + var attributes = geometry.attributes; if (typeof attributes.position === 'undefined' || typeof attributes.position.values === 'undefined') { throw new DeveloperError('geometry.attributes.position.values is required'); } + var vertices = geometry.attributes.position.values; if (geometry.attributes.position.componentsPerAttribute !== 3 || vertices.length % 3 !== 0) { throw new DeveloperError('geometry.attributes.position.values.length must be a multiple of 3'); } + if (typeof attributes.normal === 'undefined' || typeof attributes.normal.values === 'undefined') { throw new DeveloperError('geometry.attributes.normal.values is required'); } + var normals = geometry.attributes.normal.values; if (geometry.attributes.normal.componentsPerAttribute !== 3 || normals.length % 3 !== 0) { throw new DeveloperError('geometry.attributes.normals.values.length must be a multiple of 3'); } + if (typeof attributes.st === 'undefined' || typeof attributes.st.values === 'undefined') { throw new DeveloperError('geometry.attributes.st.values is required'); } + var st = geometry.attributes.st.values; if (geometry.attributes.st.componentsPerAttribute !== 2 || st.length % 2 !== 0) { throw new DeveloperError('geometry.attributes.st.values.length must be a multiple of 2'); @@ -1050,8 +1070,10 @@ define([ tan1[i23+1] += sdiry; tan1[i23+2] += sdirz; } - var binormalValues = new Array(numVertices * 3); - var tangentValues = new Array(numVertices * 3); + + var binormalValues = new Float32Array(numVertices * 3); + var tangentValues = new Float32Array(numVertices * 3); + for (i = 0; i < numVertices; i++) { i03 = i * 3; i13 = i03 + 1; @@ -1062,32 +1084,29 @@ define([ var scalar = n.dot(t); n.multiplyByScalar(scalar, normalScale); t.subtract(normalScale, t).normalize(t); + tangentValues[i03] = t.x; tangentValues[i13] = t.y; tangentValues[i23] = t.z; + n.cross(t, t).normalize(t); + binormalValues[i03] = t.x; binormalValues[i13] = t.y; binormalValues[i23] = t.z; } - if (typeof geometry.attributes.tangent === 'undefined') { - geometry.attributes.tangent = new GeometryAttribute({ - componentDatatype : ComponentDatatype.FLOAT, - componentsPerAttribute : 3, - values : tangentValues - }); - } else { - geometry.attributes.tangent.values = tangentValues; - } - if (typeof geometry.attributes.binormal === 'undefined') { - geometry.attributes.binormal = new GeometryAttribute({ - componentDatatype : ComponentDatatype.FLOAT, - componentsPerAttribute : 3, - values : binormalValues - }); - } else { - geometry.attributes.binormal.values = binormalValues; - } + + geometry.attributes.tangent = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : tangentValues + }); + + geometry.attributes.binormal = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : binormalValues + }); return geometry; }; diff --git a/Source/Core/PolygonGeometry.js b/Source/Core/PolygonGeometry.js index 636739dd5c04..3fb78cdbc33f 100644 --- a/Source/Core/PolygonGeometry.js +++ b/Source/Core/PolygonGeometry.js @@ -304,10 +304,10 @@ define([ var flatPositions = geometry.attributes.position.values; var length = flatPositions.length; - var textureCoordinates = vertexFormat.st ? new Array(2 * (length / 3)) : undefined; - var normals = vertexFormat.normal ? new Array(length) : undefined; - var tangents = vertexFormat.tangent ? new Array(length) : undefined; - var binormals = vertexFormat.binormal ? new Array(length) : undefined; + var textureCoordinates = vertexFormat.st ? new Float32Array(2 * (length / 3)) : undefined; + var normals = vertexFormat.normal ? new Float32Array(length) : undefined; + var tangents = vertexFormat.tangent ? new Float32Array(length) : undefined; + var binormals = vertexFormat.binormal ? new Float32Array(length) : undefined; var textureCoordIndex = 0; var normalIndex = 0; diff --git a/Source/Core/WallGeometry.js b/Source/Core/WallGeometry.js index 09c4879b753b..a4d5c1e2f576 100644 --- a/Source/Core/WallGeometry.js +++ b/Source/Core/WallGeometry.js @@ -106,11 +106,11 @@ define([ var i; var size = wallPositions.length * 2; - var positions = vertexFormat.position ? new Array(size * 3) : undefined; - var normals = vertexFormat.normal ? new Array(size * 3) : undefined; - var tangents = vertexFormat.tangent ? new Array(size * 3) : undefined; - var binormals = vertexFormat.binormal ? new Array(size * 3) : undefined; - var textureCoordinates = vertexFormat.st ? new Array(size * 2) : undefined; + var positions = vertexFormat.position ? new Float64Array(size * 3) : undefined; + var normals = vertexFormat.normal ? new Float32Array(size * 3) : undefined; + var tangents = vertexFormat.tangent ? new Float32Array(size * 3) : undefined; + var binormals = vertexFormat.binormal ? new Float32Array(size * 3) : undefined; + var textureCoordinates = vertexFormat.st ? new Float32Array(size * 2) : undefined; var positionIndex = 0; var normalIndex = 0; @@ -258,7 +258,7 @@ define([ // size -= 2; - var indices = new Array(size * 3); + var indices = new Uint32Array(size * 3); var j = 0; for (i = 0; i < size; i += 2) { From f01ed69c21a37cf3fc8baeb2d7d6a880a5cfbfb4 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Tue, 11 Jun 2013 19:30:45 -0400 Subject: [PATCH 158/306] Use more typed arrays and fix tests. --- Source/Core/GeometryPipeline.js | 50 +++++++++++--------- Specs/Core/EllipsoidGeometrySpec.js | 4 +- Specs/Core/GeometryPipelineSpec.js | 72 +++++++++++++++++++++-------- 3 files changed, 83 insertions(+), 43 deletions(-) diff --git a/Source/Core/GeometryPipeline.js b/Source/Core/GeometryPipeline.js index ac2abd63894b..08b9440a636f 100644 --- a/Source/Core/GeometryPipeline.js +++ b/Source/Core/GeometryPipeline.js @@ -43,54 +43,60 @@ define([ */ var GeometryPipeline = {}; - function addTriangle(lines, i0, i1, i2) { - lines.push(i0); - lines.push(i1); + function addTriangle(lines, index, i0, i1, i2) { + lines[index++] = i0; + lines[index++] = i1; - lines.push(i1); - lines.push(i2); + lines[index++] = i1; + lines[index++] = i2; - lines.push(i2); - lines.push(i0); + lines[index++] = i2; + lines[index] = i0; } function trianglesToLines(triangles) { - var lines = []; var count = triangles.length; - for ( var i = 0; i < count; i += 3) { - addTriangle(lines, triangles[i], triangles[i + 1], triangles[i + 2]); + var lines = new Uint32Array((count / 3) * 6); + var index = 0; + for ( var i = 0; i < count; i += 3, index += 6) { + addTriangle(lines, index, triangles[i], triangles[i + 1], triangles[i + 2]); } return lines; } function triangleStripToLines(triangles) { - var lines = []; var count = triangles.length; - if (count >= 3) { - addTriangle(lines, triangles[0], triangles[1], triangles[2]); + var lines = new Uint32Array((count - 2) * 6); + + addTriangle(lines, 0, triangles[0], triangles[1], triangles[2]); + var index = 6; - for ( var i = 3; i < count; ++i) { - addTriangle(lines, triangles[i - 1], triangles[i], triangles[i - 2]); + for ( var i = 3; i < count; ++i, index += 6) { + addTriangle(lines, index, triangles[i - 1], triangles[i], triangles[i - 2]); } + + return lines; } - return lines; + return []; } function triangleFanToLines(triangles) { - var lines = []; - if (triangles.length > 0) { - var base = triangles[0]; var count = triangles.length - 1; - for ( var i = 1; i < count; ++i) { - addTriangle(lines, base, triangles[i], triangles[i + 1]); + var lines = new Uint32Array((count - 1) * 6); + var base = triangles[0]; + var index = 0; + for ( var i = 1; i < count; ++i, index += 6) { + addTriangle(lines, index, base, triangles[i], triangles[i + 1]); } + + return lines; } - return lines; + return []; } /** diff --git a/Specs/Core/EllipsoidGeometrySpec.js b/Specs/Core/EllipsoidGeometrySpec.js index 3686782d649c..05972bb2250f 100644 --- a/Specs/Core/EllipsoidGeometrySpec.js +++ b/Specs/Core/EllipsoidGeometrySpec.js @@ -68,9 +68,9 @@ defineSuite([ var binormal = Cartesian3.fromArray(binormals, i); expect(position.magnitude()).toEqualEpsilon(1.0, CesiumMath.EPSILON10); - expect(normal).toEqualEpsilon(position.normalize(), CesiumMath.EPSILON10); + expect(normal).toEqualEpsilon(position.normalize(), CesiumMath.EPSILON7); expect(Cartesian3.dot(Cartesian3.UNIT_Z, tangent)).not.toBeLessThan(0.0); - expect(binormal).toEqualEpsilon(Cartesian3.cross(normal, tangent), CesiumMath.EPSILON10); + expect(binormal).toEqualEpsilon(Cartesian3.cross(normal, tangent), CesiumMath.EPSILON7); } }); }); \ No newline at end of file diff --git a/Specs/Core/GeometryPipelineSpec.js b/Specs/Core/GeometryPipelineSpec.js index 87a6c888d23d..0eb8cdcccef3 100644 --- a/Specs/Core/GeometryPipelineSpec.js +++ b/Specs/Core/GeometryPipelineSpec.js @@ -763,12 +763,17 @@ defineSuite([ geometry = GeometryPipeline.computeNormal(geometry); - expect(geometry.attributes.normal.values.length).toEqual(4*3); + var normals = geometry.attributes.normal.values; + expect(normals.length).toEqual(4*3); + var a = new Cartesian3(-1, 0, 1).normalize(); - expect(geometry.attributes.normal.values.slice(0, 3)).toEqual([a.x, a.y, a.z]); - expect(geometry.attributes.normal.values.slice(3, 9)).toEqual([0, 0, 1, 0, 0, 1]); + + expect(Cartesian3.fromArray(normals, 0)).toEqualEpsilon(a, CesiumMath.EPSILON7); + expect(Cartesian3.fromArray(normals, 3)).toEqualEpsilon(Cartesian3.UNIT_Z, CesiumMath.EPSILON7); + expect(Cartesian3.fromArray(normals, 6)).toEqualEpsilon(Cartesian3.UNIT_Z, CesiumMath.EPSILON7); + a = new Cartesian3(1, 0, 1).normalize(); - expect(geometry.attributes.normal.values.slice(9, 12)).toEqual([a.x, a.y, a.z]); + expect(Cartesian3.fromArray(normals, 9)).toEqualEpsilon(a, CesiumMath.EPSILON7); }); it('computeNormal computes normal for six triangles', function() { @@ -785,18 +790,26 @@ defineSuite([ geometry = GeometryPipeline.computeNormal(geometry); - expect(geometry.attributes.normal.values.length).toEqual(7*3); + var normals = geometry.attributes.normal.values; + expect(normals.length).toEqual(7*3); + var a = new Cartesian3(-1, -1, -1).normalize(); - expect(geometry.attributes.normal.values.slice(0, 3)).toEqual([a.x, a.y, a.z]); + expect(Cartesian3.fromArray(normals, 0)).toEqualEpsilon(a, CesiumMath.EPSILON7); + a = new Cartesian3(0, -1, -1).normalize(); - expect(geometry.attributes.normal.values.slice(3, 6)).toEqual([a.x, a.y, a.z]); - expect(geometry.attributes.normal.values.slice(6, 9)).toEqual([0, -1, 0]); + expect(Cartesian3.fromArray(normals, 3)).toEqualEpsilon(a, CesiumMath.EPSILON7); + + expect(Cartesian3.fromArray(normals, 6)).toEqualEpsilon(Cartesian3.UNIT_Y.negate(), CesiumMath.EPSILON7); + a = new Cartesian3(-1, -1, 0).normalize(); - expect(geometry.attributes.normal.values.slice(9, 12)).toEqual([a.x, a.y, a.z]); - expect(geometry.attributes.normal.values.slice(12, 15)).toEqual([-1, 0, 0]); + expect(Cartesian3.fromArray(normals, 9)).toEqualEpsilon(a, CesiumMath.EPSILON7); + + expect(Cartesian3.fromArray(normals, 12)).toEqualEpsilon(Cartesian3.UNIT_X.negate(), CesiumMath.EPSILON7); + a = new Cartesian3(-1, 0, -1).normalize(); - expect(geometry.attributes.normal.values.slice(15,18)).toEqual([a.x, a.y, a.z]); - expect(geometry.attributes.normal.values.slice(18,21)).toEqual([0, 0, -1]); + expect(Cartesian3.fromArray(normals, 15)).toEqualEpsilon(a, CesiumMath.EPSILON7); + + expect(Cartesian3.fromArray(normals, 18)).toEqualEpsilon(Cartesian3.UNIT_Z.negate(), CesiumMath.EPSILON7); }); it('computeTangentAndBinormal throws when geometry is undefined', function() { @@ -1085,21 +1098,42 @@ defineSuite([ expect(geometry.attributes.tangent.values).toEqualEpsilon([0.7071067811865475, 0, 0.7071067811865475, 0, 1, 0, 0, 1, 0, - -0.5773502691896258, 0.5773502691896258, 0.5773502691896258], CesiumMath.EPSILON8); + -0.5773502691896258, 0.5773502691896258, 0.5773502691896258], CesiumMath.EPSILON7); expect(geometry.attributes.binormal.values).toEqualEpsilon([0, 1, 0, -1, 0, 0, -1, 0, 0, - -0.4082482904638631, -0.8164965809277261, 0.4082482904638631], CesiumMath.EPSILON8); + -0.4082482904638631, -0.8164965809277261, 0.4082482904638631], CesiumMath.EPSILON7); }); it ('GeometryPipeline.computeTangentAndBinormal computes tangent and binormal for an EllipsoidGeometry', function() { - var geometry = new EllipsoidGeometry(); - var expected = new EllipsoidGeometry({ + var geometry = new EllipsoidGeometry({ + vertexFormat : new VertexFormat({ + position : true, + normal : true, + st : true + }) + }); + geometry = GeometryPipeline.computeTangentAndBinormal(geometry); + var actualTangents = geometry.attributes.tangent.values; + var actualBinormals = geometry.attributes.binormal.values; + + var expectedGeometry = new EllipsoidGeometry({ vertexFormat: VertexFormat.ALL }); + var expectedTangents = expectedGeometry.attributes.tangent.values; + var expectedBinormals = expectedGeometry.attributes.binormal.values; - geometry = GeometryPipeline.computeTangentAndBinormal(geometry); - expect(geometry.attributes.tangent.values.slice(1000,1200)).toEqualEpsilon(expected.attributes.tangent.values.slice(1000,1200), CesiumMath.EPSILON1); - expect(geometry.attributes.binormal.values.slice(1000,1200)).toEqualEpsilon(expected.attributes.binormal.values.slice(1000,1200), CesiumMath.EPSILON1); + expect(actualTangents.length).toEqual(expectedTangents.length); + expect(actualBinormals.length).toEqual(expectedBinormals.length); + + for (var i = 1000; i < 12000; i += 3) { + var actual = Cartesian3.fromArray(actualTangents, i); + var expected = Cartesian3.fromArray(expectedTangents, i); + expect(actual).toEqualEpsilon(expected, CesiumMath.EPSILON1); + + actual = Cartesian3.fromArray(actualBinormals, i); + expected = Cartesian3.fromArray(expectedBinormals, i); + expect(actual).toEqualEpsilon(expected, CesiumMath.EPSILON1); + } }); }); \ No newline at end of file From 4c34417f055757052be46761ccc35c0f7ca9d9a5 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Tue, 11 Jun 2013 20:25:17 -0400 Subject: [PATCH 159/306] Add more typed arrays and fix tests. --- Source/Core/Geometry.js | 10 +--------- Source/Core/GeometryAttribute.js | 11 +---------- Source/Core/GeometryPipeline.js | 15 ++++++++------- Specs/Core/GeometryPipelineSpec.js | 2 +- Specs/Scene/PolygonSpec.js | 4 ++-- 5 files changed, 13 insertions(+), 29 deletions(-) diff --git a/Source/Core/Geometry.js b/Source/Core/Geometry.js index 2c209cdcee4a..19f93db528ac 100644 --- a/Source/Core/Geometry.js +++ b/Source/Core/Geometry.js @@ -55,15 +55,7 @@ define([ } result.attributes = newAttributes; -// TODO: typed array or not. fastest way to copy? - var sourceValues = this.indexList; - var length = sourceValues.length; - var values = new Array(length); - for (var i = 0; i < length; ++i) { - values[i] = sourceValues[i]; - } - result.indexList = values; - + result.indexList = new Uint32Array(this.indexList); result.primitiveType = this.primitiveType; this.boundingSphere.clone(result.boundingSphere); diff --git a/Source/Core/GeometryAttribute.js b/Source/Core/GeometryAttribute.js index 4274fad04da3..ef6979bed7aa 100644 --- a/Source/Core/GeometryAttribute.js +++ b/Source/Core/GeometryAttribute.js @@ -46,16 +46,7 @@ define([ result.componentDatatype = this.componentDatatype; // Shallow copy enum result.componentsPerAttribute = this.componentsPerAttribute; result.normalize = this.normalize; - -// TODO: typed array or not. fastest way to copy? -// TODO: attribute not backed by buffer? - var sourceValues = this.values; - var length = sourceValues.length; - var values = new Array(length); - for (var i = 0; i < length; ++i) { - values[i] = sourceValues[i]; - } - result.values = values; + result.values = new this.values.constructor(this.values); return result; }; diff --git a/Source/Core/GeometryPipeline.js b/Source/Core/GeometryPipeline.js index 08b9440a636f..4f96de359147 100644 --- a/Source/Core/GeometryPipeline.js +++ b/Source/Core/GeometryPipeline.js @@ -203,7 +203,7 @@ define([ var numVertices = Geometry.computeNumberOfVertices(geometry); - var indexCrossReferenceOldToNew = new Array(numVertices); + var indexCrossReferenceOldToNew = new Int32Array(numVertices); for ( var i = 0; i < numVertices; i++) { indexCrossReferenceOldToNew[i] = -1; } @@ -213,7 +213,7 @@ define([ // Construct cross reference and reorder indices var indicesIn = indexList; var numIndices = indicesIn.length; - var indicesOut = []; + var indicesOut = new Uint32Array(numIndices); var intoIndicesIn = 0; var intoIndicesOut = 0; var nextIndex = 0; @@ -242,10 +242,11 @@ define([ var attributes = geometry.attributes; for ( var property in attributes) { if (attributes.hasOwnProperty(property) && attributes[property].values) { - var elementsIn = attributes[property].values; + var attribute = attributes[property]; + var elementsIn = attribute.values; var intoElementsIn = 0; - var numComponents = attributes[property].componentsPerAttribute; - var elementsOut = []; + var numComponents = attribute.componentsPerAttribute; + var elementsOut = attribute.componentDatatype.createTypedArray(elementsIn.length); while (intoElementsIn < numVertices) { var temp = indexCrossReferenceOldToNew[intoElementsIn]; for (i = 0; i < numComponents; i++) { @@ -253,7 +254,7 @@ define([ } ++intoElementsIn; } - attributes[property].values = elementsOut; + attribute.values = elementsOut; } } @@ -464,7 +465,7 @@ define([ // Project original positions to 2D. var wgs84Positions = geometry.attributes.position.values; - var projectedPositions = new Array(2 * wgs84Positions.length / 3); // TODO: Float64Array? + var projectedPositions = new Float64Array(2 * wgs84Positions.length / 3); var index = 0; for ( var i = 0; i < wgs84Positions.length; i += 3) { diff --git a/Specs/Core/GeometryPipelineSpec.js b/Specs/Core/GeometryPipelineSpec.js index 0eb8cdcccef3..4d8c8d9d1848 100644 --- a/Specs/Core/GeometryPipelineSpec.js +++ b/Specs/Core/GeometryPipelineSpec.js @@ -141,7 +141,7 @@ defineSuite([ }).toThrow(); }); - it('reorderForPreVertexCache reorders all indices and attributes for the pre vertex cahce', function() { + it('reorderForPreVertexCache reorders all indices and attributes for the pre vertex cache', function() { var geometry = new Geometry({ attributes : { weight : new GeometryAttribute({ diff --git a/Specs/Scene/PolygonSpec.js b/Specs/Scene/PolygonSpec.js index 58b8fd02e5f9..4aebcd6f7c39 100644 --- a/Specs/Scene/PolygonSpec.js +++ b/Specs/Scene/PolygonSpec.js @@ -334,8 +334,8 @@ defineSuite([ var sphere = BoundingSphere.fromPoints(projectedPositions); sphere.center = new Cartesian3(0.0, sphere.center.x, sphere.center.y); - expect(boundingVolume.center).toEqualEpsilon(sphere.center, CesiumMath.EPSILON9); - expect(boundingVolume.radius).toEqualEpsilon(sphere.radius, CesiumMath.EPSILON9); + expect(boundingVolume.center).toEqualEpsilon(sphere.center, CesiumMath.EPSILON2); + expect(boundingVolume.radius).toEqualEpsilon(sphere.radius, CesiumMath.EPSILON2); } it('test 2D bounding sphere from positions', function() { From dad356f175a73e177d5761d55ddc2e70e5fe087c Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Wed, 12 Jun 2013 10:20:22 -0400 Subject: [PATCH 160/306] More doc including semantics for geometry attributes / vertex format --- CHANGES.md | 5 +- Source/Core/Geometry.js | 44 ++++- Source/Core/GeometryPipeline.js | 200 +++++++++++----------- Source/Core/VertexFormat.js | 104 ++++++++++-- Specs/Core/GeometryPipelineSpec.js | 258 ++--------------------------- 5 files changed, 246 insertions(+), 365 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index a43da78ca77a..9b9891fe5fa8 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -17,15 +17,14 @@ Beta Releases * Removed `MeshFilters.mapAttributeIndices`. It was not used. * Renamed `Context.createVertexArrayFromMesh` to `Context.createVertexArrayFromGeometry`. Likewise, renamed `mesh` constructor property to `geometry`. * Renamed `ComponentDatatype.*.toTypedArray` to `ComponentDatatype.*.createTypedArray`. - * Replaced `Uniform.getFrameNumber` and `Uniform.getTime` with `Uniform.getFrameState`, which returns the full frame state. * Removed `Polygon.configureExtent`. * Renamed `PolygonPipeline.cleanUp` to `PolygonPipeline.removeDuplicates`. * Added `height` parameter to `BoundingSphere.fromExtent3D`. * Added `height` parameter to `Extent.subsample`. * Added `WallGeometry`, `PolygonGeometry`, `EllipseGeometry`, and `CircleGeometry`. * Added `GeometryPipeline.combine` to combine meshes for better batching. -* Added `GeometryPipeline.computeNormal` to find the normals of vertices in a mesh. -* Added `GeometryPipeline.computeTangentAndBinormal` to find the tangent and binormal vectors of vertices in a mesh. +* Added `GeometryPipeline.computeNormal` to compute normals for a geometry. +* Added `GeometryPipeline.computeBinormalAndTangent` to compute binormals and tangent vectors for a geometry. * Added `BoundingSphere.fromEllipsoid`. * Added `PolylinePipeline.removeDuplicates`. * Added `czm_tangentToEyeSpaceMatrix` built-in GLSL function. diff --git a/Source/Core/Geometry.js b/Source/Core/Geometry.js index 2c209cdcee4a..d087e8c86098 100644 --- a/Source/Core/Geometry.js +++ b/Source/Core/Geometry.js @@ -17,7 +17,49 @@ define([ options = defaultValue(options, defaultValue.EMPTY_OBJECT); /** - * DOC_TBA + * Attributes, which make up the geometry's vertices.. Each property in this object corresponds to a + * {@link GeometryAttribute} containing the attribute's data. + *

    + * Attributes are always stored non-interleaved in a Geometry. When geometry is prepared for rendering + * with {@link Context#createVertexArrayFromGeometry}, attributes are generally written interleaved + * into the vertex buffer for better rendering performance. + *

    + *

    + * There are reserved attribute names with well-known semantics. The following attributes + * are created by a Geometry (depending on the provided {@link VertexFormat}. + *

      + *
    • position - 3D vertex position. 64-bit floating-point (for precision). 3 components per attribute. See {@link VertexFormat.position}.
    • + *
    • normal - Normal (normalized), commonly used for lighting. 32-bit floating-point. 3 components per attribute. See {@link VertexFormat.normal}.
    • + *
    • st - 2D texture coordinate. 32-bit floating-point. 2 components per attribute. See {@link VertexFormat.st}.
    • + *
    • binormal - Binormal (normalized), used for tangent-space effects like bump mapping. 32-bit floating-point. 3 components per attribute. See {@link VertexFormat.binormal}.
    • + *
    • tangent - Tangent (normalized), used for tangent-space effects like bump mapping. 32-bit floating-point. 3 components per attribute. See {@link VertexFormat.tangent}.
    • + *
    + *

    + *

    + * The following attribute names are generally not created by a Geometry, but are added + * to a Geometry by a {@link Primitive} or {@link GeometryPipeline} functions to prepare + * the geometry for rendering. + *

      + *
    • position3DHigh - High 32 bits for encoded 64-bit position computed with {@link GeometryPipeline.encodeAttribute}. 32-bit floating-point. 4 components per attribute.
    • + *
    • position3DLow - Low 32 bits for encoded 64-bit position computed with {@link GeometryPipeline.encodeAttribute}. 32-bit floating-point. 4 components per attribute.
    • + *
    • position3DHigh - High 32 bits for encoded 64-bit 2D (Columbus view) position computed with {@link GeometryPipeline.encodeAttribute}. 32-bit floating-point. 4 components per attribute.
    • + *
    • position2DLow - Low 32 bits for encoded 64-bit 2D (Columbus view) position computed with {@link GeometryPipeline.encodeAttribute}. 32-bit floating-point. 4 components per attribute.
    • + *
    • color - RGBA color (normalized) usually from {@link GeometryInstance.color}. 32-bit floating-point. 4 components per attribute.
    • + *
    • pickColor - RGBA color used for picking, created from {@link Context#createPickId}. 32-bit floating-point. 4 components per attribute.
    • + *
    + *

    + * + * @type Object + * + * @example + * geometry.attributes = new GeometryAttribute({ + * componentDatatype : ComponentDatatype.FLOAT, + * componentsPerAttribute : 3, + * values : new Float32Array() + * }); + * + * @see GeometryAttribute + * @see VertexFormat */ this.attributes = defaultValue(options.attributes, {}); diff --git a/Source/Core/GeometryPipeline.js b/Source/Core/GeometryPipeline.js index f07da519855f..4633b873c022 100644 --- a/Source/Core/GeometryPipeline.js +++ b/Source/Core/GeometryPipeline.js @@ -143,9 +143,6 @@ define([ * * @exception {DeveloperError} geometry is required. * - * @see Context#createVertexArrayFromGeometry - * @see ShaderCache - * * @example * var attributeIndices = GeometryPipeline.createAttributeIndices(geometry); * // Example output @@ -153,6 +150,9 @@ define([ * // 'position' : 0, * // 'normal' : 1 * // } + * + * @see Context#createVertexArrayFromGeometry + * @see ShaderCache */ GeometryPipeline.createAttributeIndices = function(geometry) { if (typeof geometry === 'undefined') { @@ -183,10 +183,10 @@ define([ * @exception {DeveloperError} geometry is required. * @exception {DeveloperError} Each attribute array in geometry.attributes must have the same number of attributes. * - * @see GeometryPipeline.reorderForPostVertexCache - * * @example * geometry = GeometryPipeline.reorderForPreVertexCache(geometry); + * + * @see GeometryPipeline.reorderForPostVertexCache */ GeometryPipeline.reorderForPreVertexCache = function(geometry) { if (typeof geometry === 'undefined') { @@ -265,13 +265,13 @@ define([ * @exception {DeveloperError} geometry is required. * @exception {DeveloperError} cacheCapacity must be greater than two. * + * @example + * geometry = GeometryPipeline.reorderForPostVertexCache(geometry); + * * @see GeometryPipeline.reorderForPreVertexCache * @see * Fast Triangle Reordering for Vertex Locality and Reduced Overdraw * by Sander, Nehab, and Barczak - * - * @example - * geometry = GeometryPipeline.reorderForPostVertexCache(geometry); */ GeometryPipeline.reorderForPostVertexCache = function(geometry, cacheCapacity) { if (typeof geometry === 'undefined') { @@ -582,9 +582,25 @@ define([ } /** - * DOC_TBA + * Transforms a geometry instance to world coordinates. This is used as a prerequisite + * to batch together several instances with {@link GeometryPipeline.combine}. This changes + * the instance's modelMatrix to {@see Matrix4.IDENTITY} and transforms the + * following attributes if they are present: position, normal, + * binormal, and tangent. + * + * @param {GeometryInstance} instance The geometry instance to modify, which is modified in place. + * + * @returns {GeometryInstance} The modified instance argument, with its attributes transforms to world coordinates. * * @exception {DeveloperError} instance is required. + * + * @example + * for (var i = 0; i < instances.length; ++i) { + * GeometryPipeline.transformToWorldCoordinates(instances[i]); + * } + * var geometry = GeometryPipeline.combine(instances); + * + * @see GeometryPipeline.combine */ GeometryPipeline.transformToWorldCoordinates = function(instance) { if (typeof instance === 'undefined') { @@ -680,6 +696,14 @@ define([ * * @exception {DeveloperError} instances is required and must have length greater than zero. * @exception {DeveloperError} All instances must have the same modelMatrix. + * + * @example + * for (var i = 0; i < instances.length; ++i) { + * GeometryPipeline.transformToWorldCoordinates(instances[i]); + * } + * var geometry = GeometryPipeline.combine(instances); + * + * @see GeometryPipeline.transformToWorldCoordinates */ GeometryPipeline.combine = function(instances) { if ((typeof instances === 'undefined') || (instances.length < 1)) { @@ -710,9 +734,6 @@ define([ var sourceValues; var sourceValuesLength; - // PERFORMANCE_IDEA: Interleave here instead of createVertexArrayFromGeometry to save a copy. - // This will require adding offset and stride to the geometry. - // Combine attributes from each geometry into a single typed array for (name in attributes) { if (attributes.hasOwnProperty(name)) { @@ -827,43 +848,42 @@ define([ var v2 = new Cartesian3(); /** - * Computes the normals of all vertices in a geometry based on the normals of triangles that include the vertex. - * This assumes a counter-clockwise vertex winding order. + * Computes per-vertex normals for a geometry containing TRIANGLES by averaging the normals of + * all triangles incident to the vertex. The result is a new normal attribute added to the geometry. + * This assumes a counter-clockwise winding order. + *

    + * This function has no effect if the geometry's indexList is undefined or the + * primitiveType is not {@link PrimitiveType.TRIANGLES} or the geometry does not have a + * position attribute. + *

    * * @param {Geometry} geometry The geometry to modify, which is modified in place. - * @param {Object} geometry.attributes.position * - * @returns {Geometry} The modified geometry argument. + * @returns {Geometry} The modified geometry argument with the computed normal attribute. * - * @exception {DeveloperError} geometry.attributes.position.values is required - * @exception {DeveloperError} geometry.attributes.position.values.length must be a multiple of 3 + * @exception {DeveloperError} geometry is required * * @example * geometry = GeometryPipeline.computeNormal(geometry); - * */ GeometryPipeline.computeNormal = function(geometry) { if (typeof geometry === 'undefined') { throw new DeveloperError('geometry is required.'); } var attributes = geometry.attributes; - if (typeof attributes.position === 'undefined' || typeof attributes.position.values === 'undefined') { - throw new DeveloperError('geometry.attributes.position.values is required'); - } - var vertices = geometry.attributes.position.values; - if (geometry.attributes.position.componentsPerAttribute !== 3 || vertices.length % 3 !== 0) { - throw new DeveloperError('geometry.attributes.position.values.length must be a multiple of 3'); - } var indices = geometry.indexList; - if (typeof indices === 'undefined') { - return geometry; - } - if (geometry.primitiveType !== PrimitiveType.TRIANGLES || typeof indices === 'undefined' || - indices.length < 2 || indices.length % 3 !== 0) { + if (typeof attributes.position === 'undefined' || + typeof attributes.position.values === 'undefined' || + geometry.primitiveType !== PrimitiveType.TRIANGLES || + typeof indices === 'undefined' || + indices.length < 2 || + indices.length % 3 !== 0) { + return geometry; } + var vertices = geometry.attributes.position.values; var numVertices = geometry.attributes.position.values.length / 3; var numIndices = indices.length; var normalsPerVertex = new Array(numVertices); @@ -934,14 +954,7 @@ define([ j++; } - if (typeof geometry.attributes.normal === 'undefined') { - geometry.attributes.normal = new GeometryAttribute({ - componentDatatype: ComponentDatatype.FLOAT, - componentsPerAttribute: 3, - values: new Array(numVertices * 3) - }); - } - var normalValues = geometry.attributes.normal.values; + var normalValues = new Array(numVertices * 3); for (i = 0; i < numVertices; i++) { var i3 = i * 3; vertexNormalData = normalsPerVertex[i]; @@ -952,15 +965,21 @@ define([ } normal.normalize(normal); normalValues[i3] = normal.x; - normalValues[i3+1] = normal.y; - normalValues[i3+2] = normal.z; + normalValues[i3 + 1] = normal.y; + normalValues[i3 + 2] = normal.z; } else { normalValues[i3] = 0.0; - normalValues[i3+1] = 0.0; - normalValues[i3+2] = 1.0; + normalValues[i3 + 1] = 0.0; + normalValues[i3 + 2] = 1.0; } } + geometry.attributes.normal = new GeometryAttribute({ + componentDatatype: ComponentDatatype.FLOAT, + componentsPerAttribute: 3, + values: normalValues + }); + return geometry; }; @@ -969,62 +988,46 @@ define([ var tScratch = new Cartesian3(); /** - * Computes the tangent and binormal of all vertices in a geometry - * This assumes a counter-clockwise vertex winding order. - * - * Based on: Lengyel, Eric. Computing Tangent Space Basis Vectors for an Arbitrary Mesh. Terathon Software 3D Graphics Library, 2001. + * Computes per-vertex binormals and tangents for a geometry containing TRIANGLES. + * The result is new binormal and tangent attributes added to the geometry. + * This assumes a counter-clockwise winding order. + *

    + * This function has no effect if the geometry's indexList is undefined or the + * primitiveType is not {@link PrimitiveType.TRIANGLES} or the geometry does not have + * position, normal, and st attributes. + *

    + * Based on Computing Tangent Space Basis Vectors + * for an Arbitrary Mesh by Eric Lengyel. + *

    * * @param {Geometry} geometry The geometry to modify, which is modified in place. - * @param {Object} geometry.attributes.position The vertices of the geometry - * @param {Object} geometry.attributes.normal The normals of the vertices - * @param {Object} geometry.attributes.st The texture coordinates * - * @returns {Geometry} The modified geometry argument. + * @returns {Geometry} The modified geometry argument with the compute binormal and tangent attributes. * - * @exception {DeveloperError} geometry.attributes.position.values is required - * @exception {DeveloperError} geometry.attributes.position.values.length must be a multiple of 3 - * @exception {DeveloperError} geometry.attributes.normal.values is required - * @exception {DeveloperError} geometry.attributes.normal.values.length must be a multiple of 3 - * @exception {DeveloperError} geometry.attributes.st.values is required - * @exception {DeveloperError} geometry.attributes.st.values.length must be a multiple of 2 + * @exception {DeveloperError} geometry is required. * * @example - * geometry = GeometryPipeline.computeTangentAndBinormal(geometry); + * geometry = GeometryPipeline.computeBinormalAndTangent(geometry); */ - GeometryPipeline.computeTangentAndBinormal = function(geometry) { + GeometryPipeline.computeBinormalAndTangent = function(geometry) { if (typeof geometry === 'undefined') { throw new DeveloperError('geometry is required.'); } + var attributes = geometry.attributes; - if (typeof attributes.position === 'undefined' || typeof attributes.position.values === 'undefined') { - throw new DeveloperError('geometry.attributes.position.values is required'); - } var vertices = geometry.attributes.position.values; - if (geometry.attributes.position.componentsPerAttribute !== 3 || vertices.length % 3 !== 0) { - throw new DeveloperError('geometry.attributes.position.values.length must be a multiple of 3'); - } - if (typeof attributes.normal === 'undefined' || typeof attributes.normal.values === 'undefined') { - throw new DeveloperError('geometry.attributes.normal.values is required'); - } var normals = geometry.attributes.normal.values; - if (geometry.attributes.normal.componentsPerAttribute !== 3 || normals.length % 3 !== 0) { - throw new DeveloperError('geometry.attributes.normals.values.length must be a multiple of 3'); - } - if (typeof attributes.st === 'undefined' || typeof attributes.st.values === 'undefined') { - throw new DeveloperError('geometry.attributes.st.values is required'); - } var st = geometry.attributes.st.values; - if (geometry.attributes.st.componentsPerAttribute !== 2 || st.length % 2 !== 0) { - throw new DeveloperError('geometry.attributes.st.values.length must be a multiple of 2'); - } - var indices = geometry.indexList; - if (typeof indices === 'undefined') { - return geometry; - } - if (geometry.primitiveType !== PrimitiveType.TRIANGLES || typeof indices === 'undefined' || - indices.length < 2 || indices.length % 3 !== 0) { + if ((typeof attributes.position === 'undefined' || typeof attributes.position.values === 'undefined') || + (typeof attributes.normal === 'undefined' || typeof attributes.normal.values === 'undefined') || + (typeof attributes.st === 'undefined' || typeof attributes.st.values === 'undefined') || + geometry.primitiveType !== PrimitiveType.TRIANGLES || + typeof indices === 'undefined' || + indices.length < 2 || + indices.length % 3 !== 0) { + return geometry; } @@ -1076,6 +1079,7 @@ define([ tan1[i23+1] += sdiry; tan1[i23+2] += sdirz; } + var binormalValues = new Array(numVertices * 3); var tangentValues = new Array(numVertices * 3); for (i = 0; i < numVertices; i++) { @@ -1096,24 +1100,18 @@ define([ binormalValues[i13] = t.y; binormalValues[i23] = t.z; } - if (typeof geometry.attributes.tangent === 'undefined') { - geometry.attributes.tangent = new GeometryAttribute({ - componentDatatype : ComponentDatatype.FLOAT, - componentsPerAttribute : 3, - values : tangentValues - }); - } else { - geometry.attributes.tangent.values = tangentValues; - } - if (typeof geometry.attributes.binormal === 'undefined') { - geometry.attributes.binormal = new GeometryAttribute({ - componentDatatype : ComponentDatatype.FLOAT, - componentsPerAttribute : 3, - values : binormalValues - }); - } else { - geometry.attributes.binormal.values = binormalValues; - } + + geometry.attributes.tangent = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : tangentValues + }); + + geometry.attributes.binormal = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : binormalValues + }); return geometry; }; diff --git a/Source/Core/VertexFormat.js b/Source/Core/VertexFormat.js index eee443445237..d0079cc4d3fc 100644 --- a/Source/Core/VertexFormat.js +++ b/Source/Core/VertexFormat.js @@ -8,46 +8,96 @@ define([ "use strict"; /** - * DOC_TBA + * A vertex format defines what attributes make up a vertex. A VertexFormat can be provided + * to a {@link Geometry} to request that certain properties be computed, e.g., just position, + * position and normal, etc. + * + * @param {Object} [options=undefined] An object with boolean properties corresponding to VertexFormat properties as shown in the code example. * * @alias VertexFormat * @constructor + * + * @example + * // Create a vertex format with position and 2D texture coordinate attributes. + * var format = new VertexFormat({ + * position : true, + * st : true + * }); + * + * @see Geometry.attributes */ var VertexFormat = function(options) { options = defaultValue(options, defaultValue.EMPTY_OBJECT); /** - * DOC_TBA + * When true, the vertex has a 3D position attribute. + *

    + * 64-bit floating-point (for precision). 3 components per attribute. + *

    + * + * @type Boolean + * + * @default false */ this.position = defaultValue(options.position, false); /** - * DOC_TBA + * When true, the vertex has a normal attribute (normalized), which is commonly used for lighting. + *

    + * 32-bit floating-point. 3 components per attribute. + *

    + * + * @type Boolean + * + * @default false */ this.normal = defaultValue(options.normal, false); /** - * DOC_TBA + * When true, the vertex has a 2D texture coordinate attribute. + *

    + * 32-bit floating-point. 2 components per attribute + *

    + * + * @type Boolean + * + * @default false */ this.st = defaultValue(options.st, false); /** - * DOC_TBA + * When true, the vertex has a binormal attribute (normalized), which is used for tangent-space effects like bump mapping. + *

    + * 32-bit floating-point. 3 components per attribute. + *

    + * + * @type Boolean + * + * @default false */ this.binormal = defaultValue(options.binormal, false); /** - * DOC_TBA + * When true, the vertex has a tangent attribute (normalized), which is used for tangent-space effects like bump mapping. + *

    + * 32-bit floating-point. 3 components per attribute. + *

    + * + * @type Boolean + * + * @default false */ this.tangent = defaultValue(options.tangent, false); - - // Reserved names - // * color - for per-geometry color. - // * pickColor - for picking. }; /** - * DOC_TBA + * An immutable vertex format with position, normal, and st attributes. + * + * @memberof VertexFormat + * + * @see VertexFormat#position + * @see VertexFormat#normal + * @see VertexFormat#st */ VertexFormat.DEFAULT = freezeObject(new VertexFormat({ position : true, @@ -56,16 +106,24 @@ define([ })); /** - * DOC_TBA + * An immutable vertex format with only a position attribute. + * + * @memberof VertexFormat + * + * @see VertexFormat#position */ VertexFormat.POSITION_ONLY = freezeObject(new VertexFormat({ position : true })); /** - * DOC_TBA + * An immutable vertex format with position and normal attributes. + * This is compatible with per-geometry color appearances like {@link PerGeometryColorClosedTranslucentAppearance}. + * + * @memberof VertexFormat * - * For use with per-geometry color appearance. + * @see VertexFormat#position + * @see VertexFormat#normal */ VertexFormat.POSITION_AND_NORMAL = freezeObject(new VertexFormat({ position : true, @@ -73,9 +131,13 @@ define([ })); /** - * DOC_TBA + * An immutable vertex format with position and st attributes. + * This is compatible with {@link EllipsoidSurfaceAppearance}. * - * For use with ellipsoid-surface appearance. + * @memberof VertexFormat + * + * @see VertexFormat#position + * @see VertexFormat#st */ VertexFormat.POSITION_AND_ST = freezeObject(new VertexFormat({ position : true, @@ -83,7 +145,15 @@ define([ })); /** - * DOC_TBA + * An immutable vertex format with all well-known attributes: position, normal, st, binormal, and tangent. + * + * @memberof VertexFormat + * + * @see VertexFormat#position + * @see VertexFormat#normal + * @see VertexFormat#st + * @see VertexFormat#binormal + * @see VertexFormat#tangent */ VertexFormat.ALL = freezeObject(new VertexFormat({ position : true, diff --git a/Specs/Core/GeometryPipelineSpec.js b/Specs/Core/GeometryPipelineSpec.js index 87a6c888d23d..788f170c750f 100644 --- a/Specs/Core/GeometryPipelineSpec.js +++ b/Specs/Core/GeometryPipelineSpec.js @@ -229,10 +229,7 @@ defineSuite([ }); it('reorderForPostVertexCache reorders indices for the post vertex cache', function() { - var geometry = new EllipsoidGeometry({ - ellipsoid : new Ellipsoid(10.0, 10.0, 10.0), - numberOfPartitions : 100 - }); + var geometry = new EllipsoidGeometry(); var acmrBefore = Tipsify.calculateACMR({ indices : geometry.indexList, cacheSize : 24 @@ -656,48 +653,6 @@ defineSuite([ }).toThrow(); }); - it('computeNormal throws when geometry.attributes.position is undefined', function() { - expect(function() { - GeometryPipeline.computeNormal(new Geometry()); - }).toThrow(); - }); - - it('computeNormal throws when geometry.attributes.position.values is undefined', function() { - expect(function() { - GeometryPipeline.computeNormal(new Geometry({ - attributes: { - position: new GeometryAttribute() - } - })); - }).toThrow(); - }); - - it('computeNormal throws when geometry.attributes.position.componentsPerAttribute is not 3', function() { - expect(function() { - GeometryPipeline.computeNormal(new Geometry({ - attributes: { - position: new GeometryAttribute({ - values : [3, 2, 1, 1, 2, 4], - componentsPerAttribute : 2 - }) - } - })); - }).toThrow(); - }); - - it('computeNormal throws when geometry.attributes.position.values is not a multiple of 3', function() { - expect(function() { - GeometryPipeline.computeNormal(new Geometry( { - attributes: { - position: new GeometryAttribute({ - values: [3, 2, 1, 1, 2, 4, 3], - componentsPerAttribute: 3 - }) - } - })); - }).toThrow(); - }); - it('computeNormal does not compute normals when geometry.indexList is undefined', function() { var geometry = new Geometry({ attributes: { @@ -710,7 +665,7 @@ defineSuite([ geometry = GeometryPipeline.computeNormal(geometry); - expect(typeof geometry.attributes.normal === 'undefined').toEqual(true); + expect(geometry.attributes.normal).not.toBeDefined(); }); it('computeNormal does not compute normals when primitive type is not triangle', function() { @@ -727,7 +682,7 @@ defineSuite([ geometry = GeometryPipeline.computeNormal(geometry); - expect(typeof geometry.attributes.normal === 'undefined').toEqual(true); + expect(geometry.attributes.normal).not.toBeDefined(); }); @@ -799,196 +754,13 @@ defineSuite([ expect(geometry.attributes.normal.values.slice(18,21)).toEqual([0, 0, -1]); }); - it('computeTangentAndBinormal throws when geometry is undefined', function() { + it('computeBinormalAndTangent throws when geometry is undefined', function() { expect(function() { - GeometryPipeline.computeTangentAndBinormal(); - }).toThrow(); - }); - - it('computeTangentAndBinormal throws when geometry.attributes.position is undefined', function() { - expect(function() { - GeometryPipeline.computeTangentAndBinormal(new Geometry({ - attributes: {} - })); - }).toThrow(); - }); - - it('computeTangentAndBinormal throws when geometry.attributes.position.values is undefined', function() { - expect(function() { - GeometryPipeline.computeTangentAndBinormal(new Geometry({ - attributes: { - position: new GeometryAttribute() - } - })); - }).toThrow(); - }); - - it('computeTangentAndBinormal throws when geometry.attributes.position.componentsPerAttribute is not 3', function() { - expect(function() { - GeometryPipeline.computeTangentAndBinormal(new Geometry({ - attributes: { - position: new GeometryAttribute({ - values: [3, 2, 1, 1, 2, 4], - componentsPerAttribute: 2 - }) - } - })); - }).toThrow(); - }); - - it('computeTangentAndBinormal throws when geometry.attributes.position.values is not a multiple of 3', function() { - expect(function() { - GeometryPipeline.computeTangentAndBinormal(new Geometry({ - attributes: { - position: new GeometryAttribute({ - values: [3, 2, 1, 1, 2, 4, 3], - componentsPerAttribute: 3 - }) - } - })); - }).toThrow(); - }); - - it('computeTangentAndBinormal throws when geometry.attributes.normal is undefined', function() { - expect(function() { - GeometryPipeline.computeTangentAndBinormal(new Geometry({ - attributes: { - position: new GeometryAttribute({ - values: [0, 0, 0, 1, 0, 0, 0, 1, 0], - componentsPerAttribute: 3 - }) - } - })); - }).toThrow(); - }); - - it('computeTangentAndBinormal throws when geometry.attributes.normal.values is undefined', function() { - expect(function() { - GeometryPipeline.computeTangentAndBinormal(new Geometry({ - attributes: { - position: new GeometryAttribute({ - values: [0, 0, 0, 1, 0, 0, 0, 1, 0], - componentsPerAttribute: 3 - }), - normal: {} - } - })); - }).toThrow(); - }); - - it('computeTangentAndBinormal throws when geometry.attributes.normal.componentsPerAttribute is not 3', function() { - expect(function() { - GeometryPipeline.computeTangentAndBinormal(new Geometry({ - attributes: { - position: new GeometryAttribute({ - values: [3, 2, 1, 1, 2, 4], - componentsPerAttribute: 3 - }), - normal: new GeometryAttribute({ - values: [3, 2, 1, 1, 2, 4], - componentsPerAttribute: 2 - }) - } - })); - }).toThrow(); - }); - - it('computeTangentAndBinormal throws when geometry.attributes.normal.values is not a multiple of 3', function() { - expect(function() { - GeometryPipeline.computeTangentAndBinormal(new Geometry({ - attributes: { - position: new GeometryAttribute({ - values: [3, 2, 1, 1, 2, 3], - componentsPerAttribute: 3 - }), - normal: new GeometryAttribute({ - values: [3, 2, 1, 1, 2, 3, 4], - componentsPerAttribute: 3 - }) - } - })); - }).toThrow(); - }); - - it('computeTangentAndBinormal throws when geometry.attributes.st is undefined', function() { - expect(function() { - GeometryPipeline.computeTangentAndBinormal(new Geometry( { - attributes: { - position: new GeometryAttribute({ - values: [0, 0, 0, 1, 0, 0, 0, 1, 0], - componentsPerAttribute: 3 - - }), - normal: new GeometryAttribute({ - values: [0, 0, 0, 1, 0, 0, 0, 1, 0], - componentsPerAttribute: 3 - }) - } - })); - }).toThrow(); - }); - - it('computeTangentAndBinormal throws when geometry.attributes.normal.values is undefined', function() { - expect(function() { - GeometryPipeline.computeTangentAndBinormal(new Geometry( { - attributes: { - position: new GeometryAttribute({ - values: [0, 0, 0, 1, 0, 0, 0, 1, 0], - componentsPerAttribute: 3 - }), - normal: new GeometryAttribute({ - values: [0, 0, 0, 1, 0, 0, 0, 1, 0], - componentsPerAttribute: 3 - }), - st: new GeometryAttribute() - } - })); - }).toThrow(); - }); - - it('computeTangentAndBinormal throws when geometry.attributes.st.componentsPerAttribute is not 2', function() { - expect(function() { - GeometryPipeline.computeTangentAndBinormal(new Geometry( { - attributes: { - position: new GeometryAttribute({ - values: [0, 0, 0, 1, 0, 0, 0, 1, 0], - componentsPerAttribute: 3 - }), - normal: new GeometryAttribute({ - values: [0, 0, 0, 1, 0, 0, 0, 1, 0], - componentsPerAttribute: 3 - }), - st: new GeometryAttribute({ - values: [0, 1], - componentsPerAttribute: 3 - }) - } - })); - }).toThrow(); - }); - - it('computeTangentAndBinormal throws when geometry.attributes.st.values is not a multiple of 2', function() { - expect(function() { - GeometryPipeline.computeTangentAndBinormal(new Geometry( { - attributes: { - position: new GeometryAttribute({ - values: [0, 0, 0, 1, 0, 0, 0, 1, 0], - componentsPerAttribute: 3 - }), - normal: new GeometryAttribute({ - values: [0, 0, 0, 1, 0, 0, 0, 1, 0], - componentsPerAttribute: 3 - }), - st: new GeometryAttribute({ - values: [0, 1, 3], - componentsPerAttribute: 2 - }) - } - })); + GeometryPipeline.computeBinormalAndTangent(); }).toThrow(); }); - it('computeTangentAndBinormal does not compute tangent and binormals when geometry.indexList is undefined', function() { + it('computeBinormalAndTangent does not compute tangent and binormals when geometry.indexList is undefined', function() { var geometry = new Geometry({ attributes: { position: new GeometryAttribute({ @@ -1007,13 +779,13 @@ defineSuite([ } }); - geometry = GeometryPipeline.computeTangentAndBinormal(geometry); + geometry = GeometryPipeline.computeBinormalAndTangent(geometry); expect(typeof geometry.attributes.tangent === 'undefined').toEqual(true); expect(typeof geometry.attributes.binormal === 'undefined').toEqual(true); }); - it('computeTangentAndBinormal does not compute tangent and binormals when primitive type is not triangle', function() { + it('computeBinormalAndTangent does not compute tangent and binormals when primitive type is not triangle', function() { var geometry = new Geometry({ attributes: { position: new GeometryAttribute({ @@ -1035,13 +807,13 @@ defineSuite([ primitiveType: PrimitiveType.TRIANGLE_STRIP }); - geometry = GeometryPipeline.computeTangentAndBinormal(geometry); + geometry = GeometryPipeline.computeBinormalAndTangent(geometry); expect(typeof geometry.attributes.tangent === 'undefined').toEqual(true); expect(typeof geometry.attributes.binormal === 'undefined').toEqual(true); }); - it('computeTangentAndBinormal computes tangent and binormal for one triangle', function() { + it('computeBinormalAndTangent computes tangent and binormal for one triangle', function() { var geometry = new Geometry({ attributes: { position: new GeometryAttribute({ @@ -1058,13 +830,13 @@ defineSuite([ }); geometry = GeometryPipeline.computeNormal(geometry); - geometry = GeometryPipeline.computeTangentAndBinormal(geometry); + geometry = GeometryPipeline.computeBinormalAndTangent(geometry); expect(geometry.attributes.tangent.values).toEqual([1, 0, 0, 1, 0, 0, 1, 0, 0]); expect(geometry.attributes.binormal.values).toEqual([0, 1, 0, 0, 1, 0, 0, 1, 0]); }); - it('computeTangentAndBinormal computes tangent and binormal for two triangles', function() { + it('computeBinormalAndTangent computes tangent and binormal for two triangles', function() { var geometry = new Geometry({ attributes: { position: new GeometryAttribute({ @@ -1081,7 +853,7 @@ defineSuite([ }); geometry = GeometryPipeline.computeNormal(geometry); - geometry = GeometryPipeline.computeTangentAndBinormal(geometry); + geometry = GeometryPipeline.computeBinormalAndTangent(geometry); expect(geometry.attributes.tangent.values).toEqualEpsilon([0.7071067811865475, 0, 0.7071067811865475, 0, 1, 0, 0, 1, 0, @@ -1092,13 +864,13 @@ defineSuite([ -0.4082482904638631, -0.8164965809277261, 0.4082482904638631], CesiumMath.EPSILON8); }); - it ('GeometryPipeline.computeTangentAndBinormal computes tangent and binormal for an EllipsoidGeometry', function() { + it ('GeometryPipeline.computeBinormalAndTangent computes tangent and binormal for an EllipsoidGeometry', function() { var geometry = new EllipsoidGeometry(); var expected = new EllipsoidGeometry({ vertexFormat: VertexFormat.ALL }); - geometry = GeometryPipeline.computeTangentAndBinormal(geometry); + geometry = GeometryPipeline.computeBinormalAndTangent(geometry); expect(geometry.attributes.tangent.values.slice(1000,1200)).toEqualEpsilon(expected.attributes.tangent.values.slice(1000,1200), CesiumMath.EPSILON1); expect(geometry.attributes.binormal.values.slice(1000,1200)).toEqualEpsilon(expected.attributes.binormal.values.slice(1000,1200), CesiumMath.EPSILON1); }); From 46d3120e0d2c36076c803f038a86d90bbb630fb9 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Wed, 12 Jun 2013 12:07:53 -0400 Subject: [PATCH 161/306] Made combine work without indices --- Apps/CesiumViewer/CesiumViewer.js | 53 ++++++++++++ Source/Core/Geometry.js | 23 +++-- Source/Core/GeometryPipeline.js | 134 +++++++++++++---------------- Specs/Core/GeometryPipelineSpec.js | 114 ++++++++++++++++++++++-- 4 files changed, 236 insertions(+), 88 deletions(-) diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index 368c9f9aae7f..83a2991f9e7a 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -12,6 +12,8 @@ define([ 'Core/Matrix4', 'Core/Ellipsoid', 'Core/Extent', + 'Core/Geometry', + 'Core/GeometryAttribute', 'Core/GeometryInstance', 'Core/ExtentGeometry', 'Core/EllipseGeometry', @@ -21,6 +23,8 @@ define([ 'Core/GeometryPipeline', 'Core/VertexFormat', 'Core/Transforms', + 'Core/PrimitiveType', + 'Core/ComponentDatatype', 'Core/ScreenSpaceEventHandler', 'Core/ScreenSpaceEventType', 'Core/WallGeometry', @@ -45,6 +49,8 @@ define([ Matrix4, Ellipsoid, Extent, + Geometry, + GeometryAttribute, GeometryInstance, ExtentGeometry, EllipseGeometry, @@ -54,6 +60,8 @@ define([ GeometryPipeline, VertexFormat, Transforms, + PrimitiveType, + ComponentDatatype, ScreenSpaceEventHandler, ScreenSpaceEventType, WallGeometry, @@ -273,6 +281,51 @@ define([ }) })); + var customWithIndices = new GeometryInstance({ + geometry : new Geometry({ + attributes : { + position : new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : [ + 0.0, 0.0, 2000000.0, + 7500000.0, 0.0, 2000000.0, + 0.0, 7500000.0, 2000000.0 + ] + }) + }, + indexList : [0, 1, 1, 2, 2, 0], + primitiveType : PrimitiveType.LINES + }), + pickData : 'customWithIndices' + }); + widget.scene.getPrimitives().add(new Primitive({ + geometryInstances : customWithIndices, + appearance : new Appearance() + })); + + var customWithoutIndices = new GeometryInstance({ + geometry : new Geometry({ + attributes : { + position : new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : [ + 0.0, 0.0, 0.0, + 7500000.0, 0.0, 0.0, + 0.0, 7500000.0, 0.0 + ] + }) + }, + primitiveType : PrimitiveType.LINE_LOOP + }), + pickData : 'customWithoutIndices' + }); + widget.scene.getPrimitives().add(new Primitive({ + geometryInstances : customWithoutIndices, + appearance : new Appearance() + })); + var handler = new ScreenSpaceEventHandler(scene.getCanvas()); handler.setInputAction( function (movement) { diff --git a/Source/Core/Geometry.js b/Source/Core/Geometry.js index d087e8c86098..56553362f625 100644 --- a/Source/Core/Geometry.js +++ b/Source/Core/Geometry.js @@ -97,17 +97,26 @@ define([ } result.attributes = newAttributes; + if (typeof this.indexList !== 'undefined') { // TODO: typed array or not. fastest way to copy? - var sourceValues = this.indexList; - var length = sourceValues.length; - var values = new Array(length); - for (var i = 0; i < length; ++i) { - values[i] = sourceValues[i]; + var sourceValues = this.indexList; + var length = sourceValues.length; + var values = new Array(length); + for (var i = 0; i < length; ++i) { + values[i] = sourceValues[i]; + } + result.indexList = values; + } else { + result.indexList = undefined; } - result.indexList = values; result.primitiveType = this.primitiveType; - this.boundingSphere.clone(result.boundingSphere); + + if (typeof this.boundingSphere !== 'undefined') { + this.boundingSphere.clone(result.boundingSphere); + } else { + result.boundingSphere = undefined; + } return result; }; diff --git a/Source/Core/GeometryPipeline.js b/Source/Core/GeometryPipeline.js index 4633b873c022..b41dd70d4f2e 100644 --- a/Source/Core/GeometryPipeline.js +++ b/Source/Core/GeometryPipeline.js @@ -193,15 +193,15 @@ define([ throw new DeveloperError('geometry is required.'); } - var numVertices = Geometry.computeNumberOfVertices(geometry); - - var indexCrossReferenceOldToNew = new Array(numVertices); - for ( var i = 0; i < numVertices; i++) { - indexCrossReferenceOldToNew[i] = -1; - } - var indexList = geometry.indexList; if (typeof indexList !== 'undefined') { + var numVertices = Geometry.computeNumberOfVertices(geometry); + + var indexCrossReferenceOldToNew = new Array(numVertices); + for ( var i = 0; i < numVertices; i++) { + indexCrossReferenceOldToNew[i] = -1; + } + // Construct cross reference and reorder indices var indicesIn = indexList; var numIndices = indicesIn.length; @@ -228,24 +228,24 @@ define([ ++intoIndicesOut; } geometry.indexList = indicesOut; - } - // Reorder attributes - var attributes = geometry.attributes; - for ( var property in attributes) { - if (attributes.hasOwnProperty(property) && attributes[property].values) { - var elementsIn = attributes[property].values; - var intoElementsIn = 0; - var numComponents = attributes[property].componentsPerAttribute; - var elementsOut = []; - while (intoElementsIn < numVertices) { - var temp = indexCrossReferenceOldToNew[intoElementsIn]; - for (i = 0; i < numComponents; i++) { - elementsOut[numComponents * temp + i] = elementsIn[numComponents * intoElementsIn + i]; + // Reorder attributes + var attributes = geometry.attributes; + for ( var property in attributes) { + if (attributes.hasOwnProperty(property) && attributes[property].values) { + var elementsIn = attributes[property].values; + var intoElementsIn = 0; + var numComponents = attributes[property].componentsPerAttribute; + var elementsOut = []; + while (intoElementsIn < numVertices) { + var temp = indexCrossReferenceOldToNew[intoElementsIn]; + for (i = 0; i < numComponents; i++) { + elementsOut[numComponents * temp + i] = elementsIn[numComponents * intoElementsIn + i]; + } + ++intoElementsIn; } - ++intoElementsIn; + attributes[property].values = elementsOut; } - attributes[property].values = elementsOut; } } @@ -696,6 +696,8 @@ define([ * * @exception {DeveloperError} instances is required and must have length greater than zero. * @exception {DeveloperError} All instances must have the same modelMatrix. + * @exception {DeveloperError} All instance geometries must have an indexList or not have one. + * @exception {DeveloperError} All instance geometries must have the same primitiveType. * * @example * for (var i = 0; i < instances.length; ++i) { @@ -722,10 +724,21 @@ define([ var k; var m = instances[0].modelMatrix; + var haveIndexLists = (typeof instances[0].geometry.indexList !== 'undefined'); + var primitiveType = instances[0].geometry.primitiveType; + for (i = 1; i < length; ++i) { if (!Matrix4.equals(instances[i].modelMatrix, m)) { throw new DeveloperError('All instances must have the same modelMatrix.'); } + + if ((typeof instances[i].geometry.indexList !== 'undefined') !== haveIndexLists) { + throw new DeveloperError('All instance geometries must have an indexList or not have one.'); + } + + if (instances[i].geometry.primitiveType !== primitiveType) { + throw new DeveloperError('All instance geometries must have the same primitiveType.'); + } } // Find subset of attributes in all geometries @@ -751,68 +764,38 @@ define([ } } - // PERFORMANCE_IDEA: Could combine with fitToUnsignedShortIndices, but it would start to get ugly - // and it is not needed when OES_element_index_uint is supported. - // Combine index lists + var indexList; - // First, determine the size of a typed array per primitive type - var primitiveType = instances[0].geometry.primitiveType; - var numberOfIndices = {}; - var indices; - - for (i = 0; i < length; ++i) { - indices = instances[i].geometry.indexList; - numberOfIndices[primitiveType] = (typeof numberOfIndices[primitiveType] !== 'undefined') ? - (numberOfIndices[primitiveType] += indices.length) : indices.length; - } - - // Next, allocate a typed array for indices per primitive type - var combinedIndexLists = []; - var indexListsByPrimitiveType = {}; - - for (name in numberOfIndices) { - if (numberOfIndices.hasOwnProperty(name)) { - var num = numberOfIndices[name]; + if (haveIndexLists) { + var numberOfIndices = 0; + for (i = 0; i < length; ++i) { + numberOfIndices += instances[i].geometry.indexList.length; + } // TODO: or new Array() - if (num < 60 * 1024) { - values = new Uint16Array(num); - } else { - values = new Uint32Array(num); - } - - combinedIndexLists.push(values); - - indexListsByPrimitiveType[name] = { - values : values, - currentOffset : 0 - }; + var destIndices; + if (numberOfIndices < 60 * 1024) { + destIndices = new Uint16Array(numberOfIndices); + } else { + destIndices = new Uint32Array(numberOfIndices); } - } - - // Finally, combine index lists with the same primitive type - var offset = 0; - - for (i = 0; i < length; ++i) { - sourceValues = instances[i].geometry.indexList; - sourceValuesLength = sourceValues.length; - var destValues = indexListsByPrimitiveType[primitiveType].values; - var n = indexListsByPrimitiveType[primitiveType].currentOffset; - for (k = 0; k < sourceValuesLength; ++k) { - destValues[n++] = offset + sourceValues[k]; - } + var destOffset = 0; + var offset = 0; - indexListsByPrimitiveType[primitiveType].currentOffset = n; + for (i = 0; i < length; ++i) { + var sourceIndices = instances[i].geometry.indexList; + var sourceIndicesLen = sourceIndices.length; - var attrs = instances[i].geometry.attributes; - for (name in attrs) { - if (attrs.hasOwnProperty(name)) { - offset += attrs[name].values.length / attrs[name].componentsPerAttribute; - break; + for (k = 0; k < sourceIndicesLen; ++k) { + destIndices[destOffset++] = offset + sourceIndices[k]; } + + offset += Geometry.computeNumberOfVertices(instances[i].geometry); } + + indexList = destIndices; } // Create bounding sphere that includes all instances @@ -835,8 +818,7 @@ define([ return new Geometry({ attributes : attributes, -// TODO: cleanup combinedIndexLists - indexList : combinedIndexLists[0], + indexList : indexList, primitiveType : primitiveType, boundingSphere : boundingSphere }); diff --git a/Specs/Core/GeometryPipelineSpec.js b/Specs/Core/GeometryPipelineSpec.js index 788f170c750f..332d1ca11ded 100644 --- a/Specs/Core/GeometryPipelineSpec.js +++ b/Specs/Core/GeometryPipelineSpec.js @@ -7,6 +7,7 @@ defineSuite([ 'Core/Ellipsoid', 'Core/Cartesian3', 'Core/EncodedCartesian3', + 'Core/Matrix4', 'Core/Tipsify', 'Core/GeographicProjection', 'Core/Geometry', @@ -22,6 +23,7 @@ defineSuite([ Ellipsoid, Cartesian3, EncodedCartesian3, + Matrix4, Tipsify, GeographicProjection, Geometry, @@ -555,13 +557,13 @@ defineSuite([ it('combine combines one geometry', function() { var instance = new GeometryInstance({ geometry : new Geometry({ - attributes : new GeometryAttribute({ - position : { + attributes : { + position : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 3, values : [0.0, 0.0, 0.0] - } - }) + }) + } }) }); @@ -569,7 +571,46 @@ defineSuite([ expect(combined).toBe(instance.geometry); }); - it('combine combines several geometries', function() { + it('combine combines several geometries without indexLists', function() { + var instance = new GeometryInstance({ + geometry : new Geometry({ + attributes : { + position : new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : [0.0, 0.0, 0.0] + }) + } + }) + }); + var anotherInstance = new GeometryInstance({ + geometry : new Geometry({ + attributes : { + position : new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : [1.0, 1.0, 1.0] + }) + } + }) + }); + + var combined = GeometryPipeline.combine([instance, anotherInstance]); + expect(combined).toEqual(new Geometry({ + attributes : { + position : new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : new Float32Array([ + 0.0, 0.0, 0.0, + 1.0, 1.0, 1.0 + ]) + }) + } + })); + }); + + it('combine combines several geometries with indexLists', function() { var instance = new GeometryInstance({ geometry : new Geometry({ attributes : { @@ -647,6 +688,69 @@ defineSuite([ }).toThrow(); }); + it('combine throws when instances.modelMatrix do not match', function() { + var instance0 = new GeometryInstance({ + geometry : new Geometry({ + attributes : new GeometryAttribute({ + position : { + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : [0.0, 0.0, 0.0] + } + }) + }), + modelMatrix : Matrix4.fromScale(1.0) + }); + + var instance1 = new GeometryInstance({ + geometry : new Geometry({ + attributes : new GeometryAttribute({ + position : { + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : [0.0, 0.0, 0.0] + } + }) + }), + modelMatrix : Matrix4.fromScale(2.0) + }); + + expect(function() { + GeometryPipeline.combine([instance0, instance1]); + }).toThrow(); + }); + + it('combine throws when instance geometries do not all have or not have an indexList', function() { + var instance0 = new GeometryInstance({ + geometry : new Geometry({ + attributes : new GeometryAttribute({ + position : { + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : [0.0, 0.0, 0.0] + } + }), + indexList : [0] + }) + }); + + var instance1 = new GeometryInstance({ + geometry : new Geometry({ + attributes : new GeometryAttribute({ + position : { + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : [0.0, 0.0, 0.0] + } + }) + }) + }); + + expect(function() { + GeometryPipeline.combine([instance0, instance1]); + }).toThrow(); + }); + it('computeNormal throws when geometry is undefined', function() { expect(function() { GeometryPipeline.computeNormal(); From ea1fded3509af62da9e31214dce03175e2dd4737 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Wed, 12 Jun 2013 14:53:29 -0400 Subject: [PATCH 162/306] More doc --- Source/Core/Geometry.js | 76 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 72 insertions(+), 4 deletions(-) diff --git a/Source/Core/Geometry.js b/Source/Core/Geometry.js index 56553362f625..0783c3e9ae4f 100644 --- a/Source/Core/Geometry.js +++ b/Source/Core/Geometry.js @@ -8,10 +8,48 @@ define([ "use strict"; /** - * DOC_TBA + * A geometry representation with attributes forming vertices and optional index data + * defining primitives. Geometries and an {@link Appearance}, which describes the shading, + * can be assigned to a {@link Primitive} for visualization. A Primitive can + * be created from many heterogeneous - in many cases - geometries for performance. + *

    + * In low-level rendering code, a vertex array can be created from a geometry using + * {@link Context#createVertexArrayFromGeometry}. + *

    + *

    + * Geometries can be transformed and optimized using functions in {@link GeometryPipeline}. + *

    * * @alias Geometry * @constructor + * + * @param {Object} [options=undefined] An object with properties corresponding to Geometry properties as shown in the code example. + * + * @example + * // Create geometry with a position attribute and indexed lines. + * var positions = [ + * 0.0, 0.0, 0.0, + * 7500000.0, 0.0, 0.0, + * 0.0, 7500000.0, 0.0 + * ]; + * + * var geometry = new Geometry({ + * attributes : { + * position : new GeometryAttribute({ + * componentDatatype : ComponentDatatype.FLOAT, + * componentsPerAttribute : 3, + * values : positions + * }) + * }, + * indexList : [0, 1, 1, 2, 2, 0], + * primitiveType : PrimitiveType.LINES, + * boundingSphere : BoundingSphere.fromVertices(positions) + * }); + * + * @see Appearance + * @see Primitive + * @see Context#createVertexArrayFromGeometry + * @see GeometryPipeline */ var Geometry = function(options) { options = defaultValue(options, defaultValue.EMPTY_OBJECT); @@ -51,6 +89,8 @@ define([ * * @type Object * + * @default undefined + * * @example * geometry.attributes = new GeometryAttribute({ * componentDatatype : ComponentDatatype.FLOAT, @@ -64,17 +104,45 @@ define([ this.attributes = defaultValue(options.attributes, {}); /** - * DOC_TBA + * Optional index data that - along with {@link Geometry#primitiveType} - + * determines the primitives in the geometry. + * + * @type Array + * + * @default undefined + * + * @example + * // Two triangles with shared vertices + * geometry.primitiveType = PrimitiveType.TRIANGLES; + * geometry.indexList = new Uint16Array([0, 1, 2, 0, 2, 3]); */ this.indexList = options.indexList; /** - * DOC_TBA + * The type of primitives in the geometry. This is most often {@link PrimitiveType.TRIANGLES}, + * but can varying based on the specific geometry. + * + * @type PrimitiveType + * + * @default undefined + * + * @example + * // Two triangles with shared vertices + * geometry.primitiveType = PrimitiveType.TRIANGLES; + * geometry.indexList = new Uint16Array([0, 1, 2, 0, 2, 3]); */ this.primitiveType = options.primitiveType; /** - * DOC_TBA + * An optional bounding sphere that fully enclosed the geometry. This is + * commonly used for culling. + * + * @type BoundingSphere + * + * @default undefined + * + * @example + * geometry.boundingSphere = BoundingSphere.fromVertices(positions); */ this.boundingSphere = options.boundingSphere; }; From f000825bd89b691d58240087aaad4403a567b335 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Wed, 12 Jun 2013 15:05:34 -0400 Subject: [PATCH 163/306] Fix test --- Source/Core/GeometryPipeline.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Core/GeometryPipeline.js b/Source/Core/GeometryPipeline.js index b41dd70d4f2e..cf2c49b1977c 100644 --- a/Source/Core/GeometryPipeline.js +++ b/Source/Core/GeometryPipeline.js @@ -193,10 +193,10 @@ define([ throw new DeveloperError('geometry is required.'); } + var numVertices = Geometry.computeNumberOfVertices(geometry); + var indexList = geometry.indexList; if (typeof indexList !== 'undefined') { - var numVertices = Geometry.computeNumberOfVertices(geometry); - var indexCrossReferenceOldToNew = new Array(numVertices); for ( var i = 0; i < numVertices; i++) { indexCrossReferenceOldToNew[i] = -1; From 14ee0ce54a67d69a202d660fb56393b5789a1683 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Wed, 12 Jun 2013 17:12:25 -0400 Subject: [PATCH 164/306] Fix test after merge. --- Specs/Core/GeometryPipelineSpec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Specs/Core/GeometryPipelineSpec.js b/Specs/Core/GeometryPipelineSpec.js index 63ffaa3e507b..fad0b9f8cb69 100644 --- a/Specs/Core/GeometryPipelineSpec.js +++ b/Specs/Core/GeometryPipelineSpec.js @@ -989,7 +989,7 @@ defineSuite([ st : true }) }); - geometry = GeometryPipeline.computeTangentAndBinormal(geometry); + geometry = GeometryPipeline.computeBinormalAndTangent(geometry); var actualTangents = geometry.attributes.tangent.values; var actualBinormals = geometry.attributes.binormal.values; From 393b6f466dd947b819da9bc9cb1210b377829652 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Wed, 12 Jun 2013 17:34:33 -0400 Subject: [PATCH 165/306] Fix formating after merge. --- Source/Core/Geometry.js | 2 +- Source/Core/GeometryPipeline.js | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/Source/Core/Geometry.js b/Source/Core/Geometry.js index 45ba98c07e69..8b60f8fb41f7 100644 --- a/Source/Core/Geometry.js +++ b/Source/Core/Geometry.js @@ -166,7 +166,7 @@ define([ result.attributes = newAttributes; if (typeof this.indexList !== 'undefined') { - result.indexList = new Uint32Array(this.indexList); + result.indexList = new Uint32Array(this.indexList); } else { result.indexList = undefined; } diff --git a/Source/Core/GeometryPipeline.js b/Source/Core/GeometryPipeline.js index 0aa53600a15c..45f879a669a5 100644 --- a/Source/Core/GeometryPipeline.js +++ b/Source/Core/GeometryPipeline.js @@ -870,8 +870,6 @@ define([ } var attributes = geometry.attributes; - - var indices = geometry.indexList; if (typeof attributes.position === 'undefined' || @@ -1016,7 +1014,6 @@ define([ } var attributes = geometry.attributes; - var vertices = geometry.attributes.position.values; var normals = geometry.attributes.normal.values; var st = geometry.attributes.st.values; From 77bf19434ef5488701c47354aecdf9d24083a1f8 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Thu, 13 Jun 2013 09:30:42 -0400 Subject: [PATCH 166/306] Fixed JSHint warning --- Apps/Sandcastle/gallery/Wall.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Apps/Sandcastle/gallery/Wall.html b/Apps/Sandcastle/gallery/Wall.html index a88bfd18cbeb..618509103b56 100644 --- a/Apps/Sandcastle/gallery/Wall.html +++ b/Apps/Sandcastle/gallery/Wall.html @@ -116,7 +116,7 @@ var wall3 = new Cesium.GeometryInstance({ geometry : new Cesium.WallGeometry({ positions : ellipsoid.cartographicArrayToCartesianArray(positions), - terrain : terrain, + terrain : terrain }), pickData : 'wall3' }); From 37135d2272d404c879ae0d222d2512ea2ae6ab0e Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Thu, 13 Jun 2013 09:43:18 -0400 Subject: [PATCH 167/306] Geometry.clone - less is more --- Source/Core/BoxGeometry.js | 7 ------- Source/Core/CircleGeometry.js | 7 ------- Source/Core/EllipseGeometry.js | 7 ------- Source/Core/EllipsoidGeometry.js | 7 ------- Source/Core/ExtentGeometry.js | 7 ------- Source/Core/Geometry.js | 19 +++++++++++-------- Source/Core/GeometryInstance.js | 8 +++++--- Source/Core/PolygonGeometry.js | 7 ------- Source/Core/WallGeometry.js | 7 ------- 9 files changed, 16 insertions(+), 60 deletions(-) diff --git a/Source/Core/BoxGeometry.js b/Source/Core/BoxGeometry.js index f86be1e2d839..a8bbdf89f2ff 100644 --- a/Source/Core/BoxGeometry.js +++ b/Source/Core/BoxGeometry.js @@ -6,7 +6,6 @@ define([ './PrimitiveType', './defaultValue', './BoundingSphere', - './Geometry', './GeometryAttribute', './VertexFormat' ], function( @@ -16,7 +15,6 @@ define([ PrimitiveType, defaultValue, BoundingSphere, - Geometry, GeometryAttribute, VertexFormat) { "use strict"; @@ -379,10 +377,5 @@ define([ this.boundingSphere = new BoundingSphere(new Cartesian3(), max.subtract(min).magnitude() * 0.5); }; - /** - * DOC_TBA - */ - BoxGeometry.prototype.cloneGeometry = Geometry.prototype.cloneGeometry; - return BoxGeometry; }); \ No newline at end of file diff --git a/Source/Core/CircleGeometry.js b/Source/Core/CircleGeometry.js index d117a9610002..7f79d2b3862f 100644 --- a/Source/Core/CircleGeometry.js +++ b/Source/Core/CircleGeometry.js @@ -3,13 +3,11 @@ define([ './clone', './defaultValue', './DeveloperError', - './Geometry', './EllipseGeometry' ], function( clone, defaultValue, DeveloperError, - Geometry, EllipseGeometry) { "use strict"; @@ -85,10 +83,5 @@ define([ this.boundingSphere = ellipseGeometry.boundingSphere; }; - /** - * DOC_TBA - */ - CircleGeometry.prototype.cloneGeometry = Geometry.prototype.cloneGeometry; - return CircleGeometry; }); \ No newline at end of file diff --git a/Source/Core/EllipseGeometry.js b/Source/Core/EllipseGeometry.js index 8c0d31c79d0c..7e1d283c665e 100644 --- a/Source/Core/EllipseGeometry.js +++ b/Source/Core/EllipseGeometry.js @@ -6,7 +6,6 @@ define([ './ComponentDatatype', './DeveloperError', './Ellipsoid', - './Geometry', './GeometryAttribute', './Math', './Matrix3', @@ -20,7 +19,6 @@ define([ ComponentDatatype, DeveloperError, Ellipsoid, - Geometry, GeometryAttribute, CesiumMath, Matrix3, @@ -449,10 +447,5 @@ define([ this.boundingSphere = new BoundingSphere(center, semiMajorAxis); }; - /** - * DOC_TBA - */ - EllipseGeometry.prototype.cloneGeometry = Geometry.prototype.cloneGeometry; - return EllipseGeometry; }); \ No newline at end of file diff --git a/Source/Core/EllipsoidGeometry.js b/Source/Core/EllipsoidGeometry.js index a08180425f3b..be9cda823ce5 100644 --- a/Source/Core/EllipsoidGeometry.js +++ b/Source/Core/EllipsoidGeometry.js @@ -8,7 +8,6 @@ define([ './ComponentDatatype', './PrimitiveType', './BoundingSphere', - './Geometry', './GeometryAttribute', './VertexFormat' ], function( @@ -20,7 +19,6 @@ define([ ComponentDatatype, PrimitiveType, BoundingSphere, - Geometry, GeometryAttribute, VertexFormat) { "use strict"; @@ -333,10 +331,5 @@ define([ this.boundingSphere = BoundingSphere.fromEllipsoid(ellipsoid); }; - /** - * DOC_TBA - */ - EllipsoidGeometry.prototype.cloneGeometry = Geometry.prototype.cloneGeometry; - return EllipsoidGeometry; }); \ No newline at end of file diff --git a/Source/Core/ExtentGeometry.js b/Source/Core/ExtentGeometry.js index 0650fdbc6c81..7b97f8f56c1c 100644 --- a/Source/Core/ExtentGeometry.js +++ b/Source/Core/ExtentGeometry.js @@ -10,7 +10,6 @@ define([ './Ellipsoid', './Extent', './GeographicProjection', - './Geometry', './GeometryAttribute', './Math', './Matrix2', @@ -27,7 +26,6 @@ define([ Ellipsoid, Extent, GeographicProjection, - Geometry, GeometryAttribute, CesiumMath, Matrix2, @@ -321,10 +319,5 @@ define([ this.boundingSphere = BoundingSphere.fromExtent3D(extent, ellipsoid, surfaceHeight); }; - /** - * DOC_TBA - */ - ExtentGeometry.prototype.cloneGeometry = Geometry.prototype.cloneGeometry; - return ExtentGeometry; }); diff --git a/Source/Core/Geometry.js b/Source/Core/Geometry.js index 0783c3e9ae4f..f3b753e8b370 100644 --- a/Source/Core/Geometry.js +++ b/Source/Core/Geometry.js @@ -150,13 +150,16 @@ define([ /** * DOC_TBA */ - Geometry.prototype.cloneGeometry = function(result) { + Geometry.clone = function(geometry, result) { + if (typeof geometry === 'undefined') { + return undefined; + } + if (typeof result === 'undefined') { -// TODO: is this always what we want, for say BoxGeometry? result = new Geometry(); } - var attributes = this.attributes; + var attributes = geometry.attributes; var newAttributes = {}; for (var property in attributes) { if (attributes.hasOwnProperty(property)) { @@ -165,9 +168,9 @@ define([ } result.attributes = newAttributes; - if (typeof this.indexList !== 'undefined') { + if (typeof geometry.indexList !== 'undefined') { // TODO: typed array or not. fastest way to copy? - var sourceValues = this.indexList; + var sourceValues = geometry.indexList; var length = sourceValues.length; var values = new Array(length); for (var i = 0; i < length; ++i) { @@ -178,10 +181,10 @@ define([ result.indexList = undefined; } - result.primitiveType = this.primitiveType; + result.primitiveType = geometry.primitiveType; - if (typeof this.boundingSphere !== 'undefined') { - this.boundingSphere.clone(result.boundingSphere); + if (typeof geometry.boundingSphere !== 'undefined') { + geometry.boundingSphere.clone(result.boundingSphere); } else { result.boundingSphere = undefined; } diff --git a/Source/Core/GeometryInstance.js b/Source/Core/GeometryInstance.js index 3a16445b7bd6..9260394a69cb 100644 --- a/Source/Core/GeometryInstance.js +++ b/Source/Core/GeometryInstance.js @@ -1,10 +1,12 @@ /*global define*/ define([ './defaultValue', - './Matrix4' + './Matrix4', + './Geometry' ], function( defaultValue, - Matrix4) { + Matrix4, + Geometry) { "use strict"; /** @@ -57,7 +59,7 @@ define([ result = new GeometryInstance(); } - result.geometry = this.geometry.cloneGeometry(); // Looses type info, e.g., BoxGeometry to Geometry. + result.geometry = Geometry.clone(this.geometry); // Looses type info, e.g., BoxGeometry to Geometry. result.modelMatrix = this.modelMatrix.clone(result.modelMatrix); result.color = (typeof this.color !== 'undefined') ? this.color.clone() : undefined; result.pickData = this.pickData; // Shadow copy diff --git a/Source/Core/PolygonGeometry.js b/Source/Core/PolygonGeometry.js index 636739dd5c04..f333fb617742 100644 --- a/Source/Core/PolygonGeometry.js +++ b/Source/Core/PolygonGeometry.js @@ -10,7 +10,6 @@ define([ './DeveloperError', './Ellipsoid', './EllipsoidTangentPlane', - './Geometry', './GeometryAttribute', './GeometryInstance', './GeometryPipeline', @@ -33,7 +32,6 @@ define([ DeveloperError, Ellipsoid, EllipsoidTangentPlane, - Geometry, GeometryAttribute, GeometryInstance, GeometryPipeline, @@ -434,11 +432,6 @@ define([ this.boundingSphere = boundingSphere; }; - /** - * DOC_TBA - */ - PolygonGeometry.prototype.cloneGeometry = Geometry.prototype.cloneGeometry; - return PolygonGeometry; }); diff --git a/Source/Core/WallGeometry.js b/Source/Core/WallGeometry.js index 09c4879b753b..96c77401bf11 100644 --- a/Source/Core/WallGeometry.js +++ b/Source/Core/WallGeometry.js @@ -8,7 +8,6 @@ define([ './DeveloperError', './Ellipsoid', './EllipsoidTangentPlane', - './Geometry', './GeometryAttribute', './PolylinePipeline', './PolygonPipeline', @@ -24,7 +23,6 @@ define([ DeveloperError, Ellipsoid, EllipsoidTangentPlane, - Geometry, GeometryAttribute, PolylinePipeline, PolygonPipeline, @@ -301,11 +299,6 @@ define([ this.boundingSphere = new BoundingSphere.fromVertices(positions); }; - /** - * DOC_TBA - */ - WallGeometry.prototype.cloneGeometry = Geometry.prototype.cloneGeometry; - return WallGeometry; }); From 24ffc542277660d2d4e032c38b845201a4b6c29a Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Thu, 13 Jun 2013 10:38:03 -0400 Subject: [PATCH 168/306] More Geometry doc --- Source/Core/BoxGeometry.js | 14 ++++++--- Source/Core/CircleGeometry.js | 14 ++++++--- Source/Core/EllipseGeometry.js | 18 ++++++----- Source/Core/EllipsoidGeometry.js | 14 ++++++--- Source/Core/ExtentGeometry.js | 8 +++-- Source/Core/Geometry.js | 29 ++++++++++++++--- Source/Core/GeometryInstance.js | 54 +++++++++++++++++++++++++++----- Source/Core/PolygonGeometry.js | 54 +++++++++++++++++--------------- Source/Core/WallGeometry.js | 22 +++++++------ 9 files changed, 158 insertions(+), 69 deletions(-) diff --git a/Source/Core/BoxGeometry.js b/Source/Core/BoxGeometry.js index a8bbdf89f2ff..28bf578d93e5 100644 --- a/Source/Core/BoxGeometry.js +++ b/Source/Core/BoxGeometry.js @@ -34,9 +34,9 @@ define([ * * @example * var box = new BoxGeometry({ - * vertexFormat : VertexFormat.POSITION_ONLY, - * dimensions : new Cartesian3(500000.0, 500000.0, 500000.0), - * modelMatrix : Transforms.eastNorthUpToFixedFrame(center) + * vertexFormat : VertexFormat.POSITION_ONLY, + * dimensions : new Cartesian3(500000.0, 500000.0, 500000.0), + * modelMatrix : Transforms.eastNorthUpToFixedFrame(center) * }); */ var BoxGeometry = function(options) { @@ -354,18 +354,22 @@ define([ * true values of the {@link VertexFormat} option. * * @type Object + * + * @see Geometry.attributes */ this.attributes = attributes; /** - * The geometry indices. + * Index data that - along with {@link Geometry#primitiveType} - determines the primitives in the geometry. * * @type Array */ this.indexList = indexList; /** - * DOC_TBA + * The type of primitives in the geometry. For this geometry, it is {@link PrimitiveType.TRIANGLES}. + * + * @type PrimitiveType */ this.primitiveType = PrimitiveType.TRIANGLES; diff --git a/Source/Core/CircleGeometry.js b/Source/Core/CircleGeometry.js index 7f79d2b3862f..46711c6473fa 100644 --- a/Source/Core/CircleGeometry.js +++ b/Source/Core/CircleGeometry.js @@ -33,9 +33,9 @@ define([ * // Create a circle. * var ellipsoid = Ellipsoid.WGS84; * var circle = new CircleGeometry({ - * ellipsoid : ellipsoid, - * center : ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-75.59777, 40.03883)), - * radius : 100000.0 + * ellipsoid : ellipsoid, + * center : ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-75.59777, 40.03883)), + * radius : 100000.0 * }); */ var CircleGeometry = function(options) { @@ -60,18 +60,22 @@ define([ * true values of the {@link VertexFormat} option. * * @type Object + * + * @see Geometry.attributes */ this.attributes = ellipseGeometry.attributes; /** - * The geometry indices. + * Index data that - along with {@link Geometry#primitiveType} - determines the primitives in the geometry. * * @type Array */ this.indexList = ellipseGeometry.indexList; /** - * DOC_TBA + * The type of primitives in the geometry. For this geometry, it is {@link PrimitiveType.TRIANGLES}. + * + * @type PrimitiveType */ this.primitiveType = ellipseGeometry.primitiveType; diff --git a/Source/Core/EllipseGeometry.js b/Source/Core/EllipseGeometry.js index 7e1d283c665e..67a240f92a6e 100644 --- a/Source/Core/EllipseGeometry.js +++ b/Source/Core/EllipseGeometry.js @@ -88,11 +88,11 @@ define([ * // Create an ellipse. * var ellipsoid = Ellipsoid.WGS84; * var ellipse = new EllipseGeometry({ - * ellipsoid : ellipsoid, - * center : ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-75.59777, 40.03883)), - * semiMajorAxis : 500000.0, - * semiMinorAxis : 300000.0, - * bearing : CesiumMath.toRadians(60.0) + * ellipsoid : ellipsoid, + * center : ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-75.59777, 40.03883)), + * semiMajorAxis : 500000.0, + * semiMinorAxis : 300000.0, + * bearing : CesiumMath.toRadians(60.0) * }); */ var EllipseGeometry = function(options) { @@ -424,18 +424,22 @@ define([ * true values of the {@link VertexFormat} option. * * @type Object + * + * @see Geometry.attributes */ this.attributes = attributes; /** - * The geometry indices. + * Index data that - along with {@link Geometry#primitiveType} - determines the primitives in the geometry. * * @type Array */ this.indexList = indices; /** - * DOC_TBA + * The type of primitives in the geometry. For this geometry, it is {@link PrimitiveType.TRIANGLES}. + * + * @type PrimitiveType */ this.primitiveType = PrimitiveType.TRIANGLES; diff --git a/Source/Core/EllipsoidGeometry.js b/Source/Core/EllipsoidGeometry.js index be9cda823ce5..196dbee4ec77 100644 --- a/Source/Core/EllipsoidGeometry.js +++ b/Source/Core/EllipsoidGeometry.js @@ -124,9 +124,9 @@ define([ * * @example * var ellipsoid = new EllipsoidGeometry({ - * vertexFormat : VertexFormat.POSITION_ONLY, - * ellipsoid : new Ellipsoid(1000000.0, 500000.0, 500000.0), - * modelMatrix : Transforms.eastNorthUpToFixedFrame(center) + * vertexFormat : VertexFormat.POSITION_ONLY, + * ellipsoid : new Ellipsoid(1000000.0, 500000.0, 500000.0), + * modelMatrix : Transforms.eastNorthUpToFixedFrame(center) * }); */ var EllipsoidGeometry = function(options) { @@ -308,18 +308,22 @@ define([ * true values of the {@link VertexFormat} option. * * @type Object + * + * @see Geometry.attributes */ this.attributes = attributes; /** - * The geometry indices. + * Index data that - along with {@link Geometry#primitiveType} - determines the primitives in the geometry. * * @type Array */ this.indexList = indices; /** - * DOC_TBA + * The type of primitives in the geometry. For this geometry, it is {@link PrimitiveType.TRIANGLES}. + * + * @type PrimitiveType */ this.primitiveType = PrimitiveType.TRIANGLES; diff --git a/Source/Core/ExtentGeometry.js b/Source/Core/ExtentGeometry.js index 7b97f8f56c1c..07ae6780b375 100644 --- a/Source/Core/ExtentGeometry.js +++ b/Source/Core/ExtentGeometry.js @@ -296,18 +296,22 @@ define([ * true values of the {@link VertexFormat} option. * * @type Object + * + * @see Geometry.attributes */ this.attributes = attributes; /** - * The geometry indices. + * Index data that - along with {@link Geometry#primitiveType} - determines the primitives in the geometry. * * @type Array */ this.indexList = indices; /** - * DOC_TBA + * The type of primitives in the geometry. For this geometry, it is {@link PrimitiveType.TRIANGLES}. + * + * @type PrimitiveType */ this.primitiveType = PrimitiveType.TRIANGLES; diff --git a/Source/Core/Geometry.js b/Source/Core/Geometry.js index f3b753e8b370..2d9d5dfdb360 100644 --- a/Source/Core/Geometry.js +++ b/Source/Core/Geometry.js @@ -47,15 +47,16 @@ define([ * }); * * @see Appearance - * @see Primitive * @see Context#createVertexArrayFromGeometry + * @see GeometryInstance * @see GeometryPipeline + * @see Primitive */ var Geometry = function(options) { options = defaultValue(options, defaultValue.EMPTY_OBJECT); /** - * Attributes, which make up the geometry's vertices.. Each property in this object corresponds to a + * Attributes, which make up the geometry's vertices. Each property in this object corresponds to a * {@link GeometryAttribute} containing the attribute's data. *

    * Attributes are always stored non-interleaved in a Geometry. When geometry is prepared for rendering @@ -148,7 +149,17 @@ define([ }; /** - * DOC_TBA + * Duplicates a Geometry instance, including a deep copy of the attributes and indices. + * + * @memberof Geometry + * + * @param {Cartesian3} geometry The geometry to duplicate. If this is undefined, undefined is returned. + * @param {Cartesian3} [result] The object onto which to store the result. + * + * @return {Cartesian3} The modified result parameter or a new Geometry instance if one was not provided. + * + * @example + * result.geometry = Geometry.clone(this.geometry); */ Geometry.clone = function(geometry, result) { if (typeof geometry === 'undefined') { @@ -193,9 +204,19 @@ define([ }; /** - * DOC_TBA + * Computes the number of vertices in a geometry. The runtime is linear with + * respect to the number of attributes in a vertex, not the number of vertices. + * + * @memberof Geometry + * + * @param {Cartesian3} geometry The geometry. + * + * @return {Number} The number of vertices in the geometry. * * @exception {DeveloperError} geometries is required. + * + * @example + * var numVertices = Geometry.computeNumberOfVertices(geometry); */ Geometry.computeNumberOfVertices = function(geometry) { if (typeof geometry === 'undefined') { diff --git a/Source/Core/GeometryInstance.js b/Source/Core/GeometryInstance.js index 9260394a69cb..7efa19a96d05 100644 --- a/Source/Core/GeometryInstance.js +++ b/Source/Core/GeometryInstance.js @@ -10,21 +10,53 @@ define([ "use strict"; /** - * DOC_TBA + * Geometry instancing allows one {@link Geometry} object to be positions in several + * different locations and colored uniquely. For example, one {@link BoxGeometry} can + * be instanced several times, each with a different modelMatrix to change + * its position, rotation, and scale. * * @alias GeometryInstance * @constructor * - * @param {Geometry} [options.geometry] The geometry to instance. - * @param {Matrix4} [options.modelMatrix] The model matrix for this geometry. - * @param {Color} [options.color] The color of the geometry when a per-geometry color appearance is used. - * @param {Object} [options.pickData] DOC_TBA + * @param {Geometry} [options.geometry=undefined] The geometry to instance. + * @param {Matrix4} [options.modelMatrix=Matrix4.IDENTITY] The model matrix that transforms to transform the geometry from model to world coordinates. + * @param {Color} [options.color=undefined] The color of the instance when a per-geometry color appearance is used. + * @param {Object} [options.pickData=undefined] A user-defined object to return when the instance is picked with {@link Context.pick} + * + * @example + * // Create geometry for a box, and two instances that refer to it. + * // One instance positions the box on the bottom and colored aqua. + * // The other instance positions the box on the top and color white. + * var geometry = new BoxGeometry({ + * vertexFormat : VertexFormat.POSITION_AND_NORMAL, + * dimensions : new Cartesian3(1000000.0, 1000000.0, 500000.0) + * }), + * var instanceBottom = new GeometryInstance({ + * geometry : geometry, + * modelMatrix : Matrix4.multiplyByTranslation(Transforms.eastNorthUpToFixedFrame( + * ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-75.59777, 40.03883))), new Cartesian3(0.0, 0.0, 1000000.0)), + * color : Color.AQUA, + * pickData : 'bottom' + * }); + * var instanceTop = new GeometryInstance({ + * geometry : geometry, + * modelMatrix : Matrix4.multiplyByTranslation(Transforms.eastNorthUpToFixedFrame( + * ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-75.59777, 40.03883))), new Cartesian3(0.0, 0.0, 3000000.0)), + * color : Color.WHITE, + * pickData : 'top' + * }); + * + * @see Geometry */ var GeometryInstance = function(options) { options = defaultValue(options, defaultValue.EMPTY_OBJECT); /** - * DOC_TBA + * The geometry being instanced. + * + * @type Geometry + * + * @default undefined */ this.geometry = options.geometry; @@ -35,6 +67,8 @@ define([ * by {@link Transforms.eastNorthUpToFixedFrame}. * * @type Matrix4 + * + * @default Matrix4.IDENTITY */ this.modelMatrix = defaultValue(options.modelMatrix, Matrix4.IDENTITY.clone()); @@ -42,11 +76,17 @@ define([ * The color of the geometry when a per-geometry color appearance is used. * * @type Color + * + * @default undefined */ this.color = options.color; /** - * DOC_TBA + * User-defined object returned when the instance is picked. + * + * @default undefined + * + * @see Context.pick */ this.pickData = options.pickData; }; diff --git a/Source/Core/PolygonGeometry.js b/Source/Core/PolygonGeometry.js index f333fb617742..4b208c24e82d 100644 --- a/Source/Core/PolygonGeometry.js +++ b/Source/Core/PolygonGeometry.js @@ -147,45 +147,45 @@ define([ * * @example * // create a polygon from points - * var geometry = new Cesium.PolygonGeometry({ + * var geometry = new PolygonGeometry({ * positions : ellipsoid.cartographicArrayToCartesianArray([ - * Cesium.Cartographic.fromDegrees(-72.0, 40.0), - * Cesium.Cartographic.fromDegrees(-70.0, 35.0), - * Cesium.Cartographic.fromDegrees(-75.0, 30.0), - * Cesium.Cartographic.fromDegrees(-70.0, 30.0), - * Cesium.Cartographic.fromDegrees(-68.0, 40.0) + * Cartographic.fromDegrees(-72.0, 40.0), + * Cartographic.fromDegrees(-70.0, 35.0), + * Cartographic.fromDegrees(-75.0, 30.0), + * Cartographic.fromDegrees(-70.0, 30.0), + * Cartographic.fromDegrees(-68.0, 40.0) * ]) * }); * * // create a nested polygon with holes - * var geometryWithHole = new Cesium.PolygonGeometry({ + * var geometryWithHole = new PolygonGeometry({ * polygonHierarchy : { * positions : ellipsoid.cartographicArrayToCartesianArray([ - * Cesium.Cartographic.fromDegrees(-109.0, 30.0), - * Cesium.Cartographic.fromDegrees(-95.0, 30.0), - * Cesium.Cartographic.fromDegrees(-95.0, 40.0), - * Cesium.Cartographic.fromDegrees(-109.0, 40.0) + * Cartographic.fromDegrees(-109.0, 30.0), + * Cartographic.fromDegrees(-95.0, 30.0), + * Cartographic.fromDegrees(-95.0, 40.0), + * Cartographic.fromDegrees(-109.0, 40.0) * ]), * holes : [{ * positions : ellipsoid.cartographicArrayToCartesianArray([ - * Cesium.Cartographic.fromDegrees(-107.0, 31.0), - * Cesium.Cartographic.fromDegrees(-107.0, 39.0), - * Cesium.Cartographic.fromDegrees(-97.0, 39.0), - * Cesium.Cartographic.fromDegrees(-97.0, 31.0) + * Cartographic.fromDegrees(-107.0, 31.0), + * Cartographic.fromDegrees(-107.0, 39.0), + * Cartographic.fromDegrees(-97.0, 39.0), + * Cartographic.fromDegrees(-97.0, 31.0) * ]), * holes : [{ * positions : ellipsoid.cartographicArrayToCartesianArray([ - * Cesium.Cartographic.fromDegrees(-105.0, 33.0), - * Cesium.Cartographic.fromDegrees(-99.0, 33.0), - * Cesium.Cartographic.fromDegrees(-99.0, 37.0), - * Cesium.Cartographic.fromDegrees(-105.0, 37.0) + * Cartographic.fromDegrees(-105.0, 33.0), + * Cartographic.fromDegrees(-99.0, 33.0), + * Cartographic.fromDegrees(-99.0, 37.0), + * Cartographic.fromDegrees(-105.0, 37.0) * ]), * holes : [{ * positions : ellipsoid.cartographicArrayToCartesianArray([ - * Cesium.Cartographic.fromDegrees(-103.0, 34.0), - * Cesium.Cartographic.fromDegrees(-101.0, 34.0), - * Cesium.Cartographic.fromDegrees(-101.0, 36.0), - * Cesium.Cartographic.fromDegrees(-103.0, 36.0) + * Cartographic.fromDegrees(-103.0, 34.0), + * Cartographic.fromDegrees(-101.0, 34.0), + * Cartographic.fromDegrees(-101.0, 36.0), + * Cartographic.fromDegrees(-103.0, 36.0) * ]) * }] * }] @@ -409,18 +409,22 @@ define([ * true values of the {@link VertexFormat} option. * * @type Object + * + * @see Geometry.attributes */ this.attributes = attributes; /** - * The geometry indices. + * Index data that - along with {@link Geometry#primitiveType} - determines the primitives in the geometry. * * @type Array */ this.indexList = geometry.indexList; /** - * DOC_TBA + * The type of primitives in the geometry. For this geometry, it is {@link PrimitiveType.TRIANGLES}. + * + * @type PrimitiveType */ this.primitiveType = geometry.primitiveType; diff --git a/Source/Core/WallGeometry.js b/Source/Core/WallGeometry.js index 96c77401bf11..2d26b3e46dbd 100644 --- a/Source/Core/WallGeometry.js +++ b/Source/Core/WallGeometry.js @@ -60,16 +60,16 @@ define([ * * @example * var positions = [ - * Cesium.Cartographic.fromDegrees(19.0, 47.0, 10000.0), - * Cesium.Cartographic.fromDegrees(19.0, 48.0, 10000.0), - * Cesium.Cartographic.fromDegrees(20.0, 48.0, 10000.0), - * Cesium.Cartographic.fromDegrees(20.0, 47.0, 10000.0), - * Cesium.Cartographic.fromDegrees(19.0, 47.0, 10000.0) + * Cartographic.fromDegrees(19.0, 47.0, 10000.0), + * Cartographic.fromDegrees(19.0, 48.0, 10000.0), + * Cartographic.fromDegrees(20.0, 48.0, 10000.0), + * Cartographic.fromDegrees(20.0, 47.0, 10000.0), + * Cartographic.fromDegrees(19.0, 47.0, 10000.0) * ]; * * // create a wall that spans from ground level to 10000 meters - * var wall = new Cesium.WallGeometry({ - * positions : ellipsoid.cartographicArrayToCartesianArray(positions) + * var wall = new WallGeometry({ + * positions : ellipsoid.cartographicArrayToCartesianArray(positions) * }); */ var WallGeometry = function(options) { @@ -276,18 +276,22 @@ define([ * true values of the {@link VertexFormat} option. * * @type Object + * + * @see Geometry.attributes */ this.attributes = attributes; /** - * The geometry indices. + * Index data that - along with {@link Geometry#primitiveType} - determines the primitives in the geometry. * * @type Array */ this.indexList = indices; /** - * DOC_TBA + * The type of primitives in the geometry. For this geometry, it is {@link PrimitiveType.TRIANGLES}. + * + * @type PrimitiveType */ this.primitiveType = PrimitiveType.TRIANGLES; From 2103051e1b4b0fb1b9a144a2a2f295efd9a1df8a Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Thu, 13 Jun 2013 13:27:48 -0400 Subject: [PATCH 169/306] Added doc for Primitive --- Apps/CesiumViewer/CesiumViewer.js | 2 +- Source/Scene/CustomSensorVolume.js | 9 +- Source/Scene/EllipsoidPrimitive.js | 10 +- Source/Scene/Primitive.js | 145 +++++++++++++++++- .../Scene/RectangularPyramidSensorVolume.js | 9 +- Source/Scene/SkyAtmosphere.js | 5 +- Source/Scene/SkyBox.js | 5 +- Source/Scene/Sun.js | 5 +- Source/Scene/ViewportQuad.js | 7 +- 9 files changed, 162 insertions(+), 35 deletions(-) diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index 83a2991f9e7a..08977c312fd9 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -142,7 +142,7 @@ define([ height : 1000000.0 }), pickData : 'geometry4', - color : Color.LIME + color : new Color(1.0, 1.0, 0.0, 0.5) }); var primitive = new Primitive({ geometryInstances : [geometry, geometry2, geometry3, geometry4], diff --git a/Source/Scene/CustomSensorVolume.js b/Source/Scene/CustomSensorVolume.js index 054c5363a8cc..251af361acd3 100644 --- a/Source/Scene/CustomSensorVolume.js +++ b/Source/Scene/CustomSensorVolume.js @@ -79,10 +79,12 @@ define([ this.show = defaultValue(options.show, true); /** - * When true, a polyline is shown where the sensor outline intersections the central body. The default is true. + * When true, a polyline is shown where the sensor outline intersections the central body. * * @type Boolean * + * @default true + * * @see CustomSensorVolume#intersectionColor */ this.showIntersection = defaultValue(options.showIntersection, true); @@ -92,11 +94,10 @@ define([ * Determines if a sensor intersecting the ellipsoid is drawn through the ellipsoid and potentially out * to the other side, or if the part of the sensor intersecting the ellipsoid stops at the ellipsoid. *

    - *

    - * The default is false, meaning the sensor will not go through the ellipsoid. - *

    * * @type Boolean + * + * @default false */ this.showThroughEllipsoid = defaultValue(options.showThroughEllipsoid, false); this._showThroughEllipsoid = this.showThroughEllipsoid; diff --git a/Source/Scene/EllipsoidPrimitive.js b/Source/Scene/EllipsoidPrimitive.js index 70c3b318dc6f..ab308651f748 100644 --- a/Source/Scene/EllipsoidPrimitive.js +++ b/Source/Scene/EllipsoidPrimitive.js @@ -113,12 +113,11 @@ define([ * Local reference frames can be used by providing a different transformation matrix, like that returned * by {@link Transforms.eastNorthUpToFixedFrame}. This matrix is available to GLSL vertex and fragment * shaders via {@link czm_model} and derived uniforms. - *

    - * The default is {@link Matrix4.IDENTITY}. - *

    * * @type Matrix4 * + * @default Matrix4.IDENTITY + * * @example * var origin = ellipsoid.cartographicToCartesian( * Cartographic.fromDegrees(-95.0, 40.0, 200000.0)); @@ -132,11 +131,10 @@ define([ /** * Determines if the ellipsoid primitive will be shown. - *

    - * The default is true. - *

    * * @type Boolean + * + * @default true */ this.show = true; diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index 6849a3583498..4505e618307a 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -38,13 +38,97 @@ define([ "use strict"; /** - * DOC_TBA + * A primitive represents geometry in the {@link Scene}. The geometry can be from a single {@link GeometryInstance} + * as shown in Code Example 1 below, or from an array of instances, even if the geometry is from different + * geometry types, e.g., an {@link ExtentGeometry} and an {@link EllipsoidGeometry} as shown in Code Example 2. + *

    + * A primitive combines geometry instances with an {@link Appearance} that describes the full shading, including + * {@link Material} and {@link Renderstate}. Roughly, the geometry instance defines the structure and placement, + * and the appearance defines the visual characteristics. Decoupling geometry and appearance allows us to mix + * and max most of them, and to easily add new geometry types and appearances. + *

    + *

    + * Combing multiple instances in one primitive is called batching, and significantly improves performance for static data. + * Instances can be individually picked; {@link Context.pick} returns their {@link GeometryInstance#pickData}. Using + * per-instance appearances like {@link PerGeometryColorClosedTranslucentAppearance}, each instance can also have a unique color. + *

    + * + * @alias Geometry + * @constructor + * + * @param {Array} [options.geometryInstances=undefined] The geometry instances - or a single geometry instance - to render. + * @param {Appearance} [options.appearance=undefined] The appearance used to render the primitive. + * @param {Boolean} [options.vertexCacheOptimize=true] When true, geometry vertices are optimized for the pre- and post-vertex-shader caches. + * @param {Boolean} [options.releaseGeometries=true] When true, the primitive does not keep a reference to the input geometryInstances to save memory. + * @param {Boolean} [options.transformToWorldCoordinates=true] When true, each geometry instance is transform to world coordinates even if they are already in the same coordinate system. + * + * @example + * // 1. Draw a translucent ellipse on the surface with a checkerboard pattern + * var instance = new GeometryInstance({ + * geometry : new EllipseGeometry({ + * vertexFormat : VertexFormat.POSITION_AND_ST, + * ellipsoid : ellipsoid, + * center : ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-100, 20)), + * semiMinorAxis : 500000.0, + * semiMajorAxis : 1000000.0, + * bearing : CesiumMath.PI_OVER_FOUR + * }), + * pickData : 'object returned when this instance is picked' + * }); + * var primitive = new Primitive({ + * geometryInstances : instance, + * appearance : new EllipsoidSurfaceAppearance({ + * material : Material.fromType(scene.getContext(), 'Checkerboard') + * }) + * }); + * scene.getPrimitives().add(primitive); + * + * // 2. Draw different instances each with a unique color + * var extentInstance = new GeometryInstance({ + * geometry : new ExtentGeometry({ + * vertexFormat : VertexFormat.POSITION_AND_NORMAL, + * extent : new Extent( + * CesiumMath.toRadians(-140.0), + * CesiumMath.toRadians(30.0), + * CesiumMath.toRadians(-100.0), + * CesiumMath.toRadians(40.0)) + * }), + * pickData : 'object returned when this extent is picked', + * color : new Color(0.0, 1.0, 1.0, 0.5) + * }); + * var ellipsoidInstance = new GeometryInstance({ + * geometry : new EllipsoidGeometry({ + * vertexFormat : VertexFormat.POSITION_AND_NORMAL, + * ellipsoid : new Ellipsoid(500000.0, 500000.0, 1000000.0) + * }), + * modelMatrix : Matrix4.multiplyByTranslation(Transforms.eastNorthUpToFixedFrame( + * ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-95.59777, 40.03883))), new Cartesian3(0.0, 0.0, 500000.0)), + * pickData : 'object returned when this ellipsoid is picked', + * color : new Color(1.0, 0.0, 1.0, 0.5) + * }); + * var primitive = new Primitive({ + * geometryInstances : [extentInstance, ellipsoidInstance], + * appearance : new PerGeometryColorClosedTranslucentAppearance() + * }); + * scene.getPrimitives().add(primitive); + * + * @see GeometryInstance + * @see Appearance */ var Primitive = function(options) { options = defaultValue(options, defaultValue.EMPTY_OBJECT); /** - * DOC_TBA + * The geometry instances rendered with this primitive. This may + * be undefined if options.releaseGeometries + * is true when the primitive is constructed. + *

    + * Changing this property after the primitive is rendered has no effect. + *

    + * + * @type Array + * + * @default undefined */ this.geometryInstances = options.geometryInstances; @@ -54,17 +138,37 @@ define([ this.appearance = options.appearance; /** - * DOC_TBA + * The 4x4 transformation matrix that transforms the primitive (all geometry instances) from model to world coordinates. + * When this is the identity matrix, the primitive is drawn in world coordinates, i.e., Earth's WGS84 coordinates. + * Local reference frames can be used by providing a different transformation matrix, like that returned + * by {@link Transforms.eastNorthUpToFixedFrame}. This matrix is available to GLSL vertex and fragment + * shaders via {@link czm_model} and derived uniforms. + * + * @type Matrix4 + * + * @default Matrix4.IDENTITY + * + * @example + * var origin = ellipsoid.cartographicToCartesian( + * Cartographic.fromDegrees(-95.0, 40.0, 200000.0)); + * p.modelMatrix = Transforms.eastNorthUpToFixedFrame(origin); + * + * @see czm_model */ this.modelMatrix = Matrix4.IDENTITY.clone(); /** - * DOC_TBA + * Determines if the primitive will be shown. This affects all geometry + * instances in the primitive. + * + * @type Boolean + * + * @default true */ this.show = true; this._vertexCacheOptimize = defaultValue(options.vertexCacheOptimize, true); - this._releaseGeometries = defaultValue(options.releaseGeometries, false); + this._releaseGeometries = defaultValue(options.releaseGeometries, true); // When true, geometry is transformed to world coordinates even if there is a single // geometry or all geometries are in the same reference frame. this._transformToWorldCoordinates = defaultValue(options.transformToWorldCoordinates, true); @@ -436,14 +540,41 @@ define([ }; /** - * DOC_TBA + * Returns true if this object was destroyed; otherwise, false. + *

    + * If this object was destroyed, it should not be used; calling any function other than + * isDestroyed will result in a {@link DeveloperError} exception. + *

    + * + * @memberof Primitive + * + * @return {Boolean} true if this object was destroyed; otherwise, false. + * + * @see Primitive#destroy */ Primitive.prototype.isDestroyed = function() { return false; }; /** - * DOC_TBA + * Destroys the WebGL resources held by this object. Destroying an object allows for deterministic + * release of WebGL resources, instead of relying on the garbage collector to destroy this object. + *

    + * Once an object is destroyed, it should not be used; calling any function other than + * isDestroyed will result in a {@link DeveloperError} exception. Therefore, + * assign the return value (undefined) to the object as done in the example. + *

    + * + * @memberof Primitive + * + * @return {undefined} + * + * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called. + * + * @see Primitive#isDestroyed + * + * @example + * e = e && e.destroy(); */ Primitive.prototype.destroy = function() { var length; diff --git a/Source/Scene/RectangularPyramidSensorVolume.js b/Source/Scene/RectangularPyramidSensorVolume.js index 2adb603d91cf..c5013dcdb934 100644 --- a/Source/Scene/RectangularPyramidSensorVolume.js +++ b/Source/Scene/RectangularPyramidSensorVolume.js @@ -42,10 +42,12 @@ define([ this.show = defaultValue(options.show, true); /** - * When true, a polyline is shown where the sensor outline intersections the central body. The default is true. + * When true, a polyline is shown where the sensor outline intersections the central body. * * @type Boolean * + * @default true + * * @see RectangularPyramidSensorVolume#intersectionColor */ this.showIntersection = defaultValue(options.showIntersection, true); @@ -55,11 +57,10 @@ define([ * Determines if a sensor intersecting the ellipsoid is drawn through the ellipsoid and potentially out * to the other side, or if the part of the sensor intersecting the ellipsoid stops at the ellipsoid. *

    - *

    - * The default is false, meaning the sensor will not go through the ellipsoid. - *

    * * @type Boolean + * + * @default false */ this.showThroughEllipsoid = defaultValue(options.showThroughEllipsoid, false); diff --git a/Source/Scene/SkyAtmosphere.js b/Source/Scene/SkyAtmosphere.js index 13a029250f9c..7104be50aa86 100644 --- a/Source/Scene/SkyAtmosphere.js +++ b/Source/Scene/SkyAtmosphere.js @@ -52,11 +52,10 @@ define([ /** * Determines if the atmosphere is shown. - *

    - * The default is true. - *

    * * @type Boolean + * + * @default true */ this.show = true; diff --git a/Source/Scene/SkyBox.js b/Source/Scene/SkyBox.js index d9d3198e1b9c..6da875315b4f 100644 --- a/Source/Scene/SkyBox.js +++ b/Source/Scene/SkyBox.js @@ -85,11 +85,10 @@ define([ /** * Determines if the sky box will be shown. - *

    - * The default is true. - *

    * * @type Boolean + * + * @default true */ this.show = true; }; diff --git a/Source/Scene/Sun.js b/Source/Scene/Sun.js index 6b5efc0f22dd..928d71311929 100644 --- a/Source/Scene/Sun.js +++ b/Source/Scene/Sun.js @@ -50,11 +50,10 @@ define([ /** * Determines if the sun will be shown. - *

    - * The default is true. - *

    * * @type Boolean + * + * @default true */ this.show = true; }; diff --git a/Source/Scene/ViewportQuad.js b/Source/Scene/ViewportQuad.js index ee63ea19a494..54e4c087a9f3 100644 --- a/Source/Scene/ViewportQuad.js +++ b/Source/Scene/ViewportQuad.js @@ -60,12 +60,11 @@ define([ /** * Determines if the viewport quad primitive will be shown. - *

    - * The default is true. - *

    * * @type Boolean - */ + * + * @default true + */ this.show = true; if (typeof rectangle === 'undefined') { From 632dd0124673b7931b54be03361ccf6412fe9bbc Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Thu, 13 Jun 2013 13:31:08 -0400 Subject: [PATCH 170/306] Rename PerGeometry to PerInstance --- Apps/CesiumViewer/CesiumViewer.js | 6 +++--- Source/Core/GeometryInstance.js | 4 ++-- Source/Core/VertexFormat.js | 2 +- ...GeometryColorClosedTranslucentAppearance.js | 18 +++++++++--------- Source/Scene/Primitive.js | 6 +++--- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index 08977c312fd9..4074fa17bdd2 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -31,7 +31,7 @@ define([ 'Scene/Primitive', 'Scene/Appearance', 'Scene/ClosedTranslucentAppearance', - 'Scene/PerGeometryColorClosedTranslucentAppearance', + 'Scene/PerInstanceColorClosedTranslucentAppearance', 'Scene/EllipsoidSurfaceAppearance', 'Scene/Material', 'Widgets/Dojo/checkForChromeFrame', @@ -68,7 +68,7 @@ define([ Primitive, Appearance, ClosedTranslucentAppearance, - PerGeometryColorClosedTranslucentAppearance, + PerInstanceColorClosedTranslucentAppearance, EllipsoidSurfaceAppearance, Material, checkForChromeFrame, @@ -146,7 +146,7 @@ define([ }); var primitive = new Primitive({ geometryInstances : [geometry, geometry2, geometry3, geometry4], - appearance : new PerGeometryColorClosedTranslucentAppearance() + appearance : new PerInstanceColorClosedTranslucentAppearance() }); scene.getPrimitives().add(primitive); diff --git a/Source/Core/GeometryInstance.js b/Source/Core/GeometryInstance.js index 7efa19a96d05..d6681ee91afe 100644 --- a/Source/Core/GeometryInstance.js +++ b/Source/Core/GeometryInstance.js @@ -20,7 +20,7 @@ define([ * * @param {Geometry} [options.geometry=undefined] The geometry to instance. * @param {Matrix4} [options.modelMatrix=Matrix4.IDENTITY] The model matrix that transforms to transform the geometry from model to world coordinates. - * @param {Color} [options.color=undefined] The color of the instance when a per-geometry color appearance is used. + * @param {Color} [options.color=undefined] The color of the instance when a per-instance color appearance is used. * @param {Object} [options.pickData=undefined] A user-defined object to return when the instance is picked with {@link Context.pick} * * @example @@ -73,7 +73,7 @@ define([ this.modelMatrix = defaultValue(options.modelMatrix, Matrix4.IDENTITY.clone()); /** - * The color of the geometry when a per-geometry color appearance is used. + * The color of the geometry when a per-instance color appearance is used. * * @type Color * diff --git a/Source/Core/VertexFormat.js b/Source/Core/VertexFormat.js index d0079cc4d3fc..04cbc3d73dd8 100644 --- a/Source/Core/VertexFormat.js +++ b/Source/Core/VertexFormat.js @@ -118,7 +118,7 @@ define([ /** * An immutable vertex format with position and normal attributes. - * This is compatible with per-geometry color appearances like {@link PerGeometryColorClosedTranslucentAppearance}. + * This is compatible with per-instance color appearances like {@link PerInstanceColorClosedTranslucentAppearance}. * * @memberof VertexFormat * diff --git a/Source/Scene/PerGeometryColorClosedTranslucentAppearance.js b/Source/Scene/PerGeometryColorClosedTranslucentAppearance.js index 08f5d7e6c2a1..54c180871396 100644 --- a/Source/Scene/PerGeometryColorClosedTranslucentAppearance.js +++ b/Source/Scene/PerGeometryColorClosedTranslucentAppearance.js @@ -3,20 +3,20 @@ define([ '../Core/defaultValue', '../Renderer/CullFace', '../Renderer/BlendingState', - '../Shaders/Appearances/PerGeometryColorAppearanceVS', - '../Shaders/Appearances/PerGeometryColorAppearanceFS' + '../Shaders/Appearances/PerInstanceColorAppearanceVS', + '../Shaders/Appearances/PerInstanceColorAppearanceFS' ], function( defaultValue, CullFace, BlendingState, - PerGeometryColorAppearanceVS, - PerGeometryColorDefaultAppearanceFS) { + PerInstanceColorAppearanceVS, + PerInstanceColorDefaultAppearanceFS) { "use strict"; /** * DOC_TBA */ - var PerGeometryColorClosedTranslucentAppearance = function(options) { + var PerInstanceColorClosedTranslucentAppearance = function(options) { options = defaultValue(options, defaultValue.EMPTY_OBJECT); /** @@ -27,12 +27,12 @@ define([ /** * DOC_TBA */ - this.vertexShaderSource = defaultValue(options.vertexShaderSource, PerGeometryColorAppearanceVS); + this.vertexShaderSource = defaultValue(options.vertexShaderSource, PerInstanceColorAppearanceVS); /** * DOC_TBA */ - this.fragmentShaderSource = defaultValue(options.fragmentShaderSource, PerGeometryColorDefaultAppearanceFS); + this.fragmentShaderSource = defaultValue(options.fragmentShaderSource, PerInstanceColorDefaultAppearanceFS); /** * DOC_TBA @@ -53,10 +53,10 @@ define([ /** * DOC_TBA */ - PerGeometryColorClosedTranslucentAppearance.prototype.getFragmentShaderSource = function() { + PerInstanceColorClosedTranslucentAppearance.prototype.getFragmentShaderSource = function() { // Unlike other appearances, this does not have a material return this.fragmentShaderSource; }; - return PerGeometryColorClosedTranslucentAppearance; + return PerInstanceColorClosedTranslucentAppearance; }); \ No newline at end of file diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index 4505e618307a..eb3f3bb944b1 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -50,7 +50,7 @@ define([ *

    * Combing multiple instances in one primitive is called batching, and significantly improves performance for static data. * Instances can be individually picked; {@link Context.pick} returns their {@link GeometryInstance#pickData}. Using - * per-instance appearances like {@link PerGeometryColorClosedTranslucentAppearance}, each instance can also have a unique color. + * per-instance appearances like {@link PerInstanceColorClosedTranslucentAppearance}, each instance can also have a unique color. *

    * * @alias Geometry @@ -108,7 +108,7 @@ define([ * }); * var primitive = new Primitive({ * geometryInstances : [extentInstance, ellipsoidInstance], - * appearance : new PerGeometryColorClosedTranslucentAppearance() + * appearance : new PerInstanceColorClosedTranslucentAppearance() * }); * scene.getPrimitives().add(primitive); * @@ -397,7 +397,7 @@ define([ insts[i] = instances[i].clone(); } - // Add color attribute if any geometries have per-geometry color + // Add color attribute if any geometries have per-instance color if (hasPerInstanceColor(insts)) { addColorAttribute(primitive, insts, context); } From f4d097d55c5dd8f7690f83cd00f945d786b354e2 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Thu, 13 Jun 2013 13:35:52 -0400 Subject: [PATCH 171/306] File rename PerGeometry to PerInstance --- ...pearance.js => PerInstanceColorClosedTranslucentAppearance.js} | 0 ...ryColorAppearanceFS.glsl => PerInstanceColorAppearanceFS.glsl} | 0 ...ryColorAppearanceVS.glsl => PerInstanceColorAppearanceVS.glsl} | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename Source/Scene/{PerGeometryColorClosedTranslucentAppearance.js => PerInstanceColorClosedTranslucentAppearance.js} (100%) rename Source/Shaders/Appearances/{PerGeometryColorAppearanceFS.glsl => PerInstanceColorAppearanceFS.glsl} (100%) rename Source/Shaders/Appearances/{PerGeometryColorAppearanceVS.glsl => PerInstanceColorAppearanceVS.glsl} (100%) diff --git a/Source/Scene/PerGeometryColorClosedTranslucentAppearance.js b/Source/Scene/PerInstanceColorClosedTranslucentAppearance.js similarity index 100% rename from Source/Scene/PerGeometryColorClosedTranslucentAppearance.js rename to Source/Scene/PerInstanceColorClosedTranslucentAppearance.js diff --git a/Source/Shaders/Appearances/PerGeometryColorAppearanceFS.glsl b/Source/Shaders/Appearances/PerInstanceColorAppearanceFS.glsl similarity index 100% rename from Source/Shaders/Appearances/PerGeometryColorAppearanceFS.glsl rename to Source/Shaders/Appearances/PerInstanceColorAppearanceFS.glsl diff --git a/Source/Shaders/Appearances/PerGeometryColorAppearanceVS.glsl b/Source/Shaders/Appearances/PerInstanceColorAppearanceVS.glsl similarity index 100% rename from Source/Shaders/Appearances/PerGeometryColorAppearanceVS.glsl rename to Source/Shaders/Appearances/PerInstanceColorAppearanceVS.glsl From 5c58b4ea76332a30914b8677e03dc43cc0329d3e Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Thu, 13 Jun 2013 13:47:43 -0400 Subject: [PATCH 172/306] Updated CHANGES.md --- CHANGES.md | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 9b9891fe5fa8..352df3cf898b 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -21,12 +21,25 @@ Beta Releases * Renamed `PolygonPipeline.cleanUp` to `PolygonPipeline.removeDuplicates`. * Added `height` parameter to `BoundingSphere.fromExtent3D`. * Added `height` parameter to `Extent.subsample`. -* Added `WallGeometry`, `PolygonGeometry`, `EllipseGeometry`, and `CircleGeometry`. +* Added `Geometry` and `GeometryInstance`. Added the following geometry types: + * `PolygonGeometry` + * `ExtentGeometry` + * `EllipseGeometry` + * `CircleGeometry` + * `WallGeometry` + * `BoxGeometry` + * `EllipsoidGeometry` +* Added `Appearance`, which describe the visual characteristics for geometry instances. Added the following types: + * `TranslucentAppearance` + * `EllipsoidSurfaceAppearance` + * `ClosedTranslucentAppearance` + * `PerInstanceColorClosedTranslucentAppearance` +* Added `Primitive`, which is a generic primitive that combines geometry instances and appearances. * Added `GeometryPipeline.combine` to combine meshes for better batching. * Added `GeometryPipeline.computeNormal` to compute normals for a geometry. * Added `GeometryPipeline.computeBinormalAndTangent` to compute binormals and tangent vectors for a geometry. -* Added `BoundingSphere.fromEllipsoid`. * Added `PolylinePipeline.removeDuplicates`. +* Added `BoundingSphere.fromEllipsoid`. * Added `czm_tangentToEyeSpaceMatrix` built-in GLSL function. * Improved the performance of drawing polygons created with `configureFromPolygonHierarchy`. From bf736a5c83c95ee9217ecaa8ccccc777f3eb1831 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Thu, 13 Jun 2013 14:03:03 -0400 Subject: [PATCH 173/306] Fix some TODOs in tests --- Source/Renderer/PickFramebuffer.js | 3 --- Specs/Renderer/VertexArrayFactorySpec.js | 5 ++--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/Source/Renderer/PickFramebuffer.js b/Source/Renderer/PickFramebuffer.js index 9ab12a217d5f..7096e7b6b31a 100644 --- a/Source/Renderer/PickFramebuffer.js +++ b/Source/Renderer/PickFramebuffer.js @@ -88,9 +88,6 @@ define([ framebuffer : this._fb }); -// TODO: remove -console.log(pixels[0] + ', ' + pixels[1] + ', ' + pixels[2] + ', ' + pixels[3]); - var max = Math.max(width, height); var length = max * max; var halfWidth = Math.floor(width * 0.5); diff --git a/Specs/Renderer/VertexArrayFactorySpec.js b/Specs/Renderer/VertexArrayFactorySpec.js index 4eb3c180ed66..4fe2ba121318 100644 --- a/Specs/Renderer/VertexArrayFactorySpec.js +++ b/Specs/Renderer/VertexArrayFactorySpec.js @@ -311,12 +311,12 @@ defineSuite([ }); it('sorts interleaved attributes from large to small components (2)', function() { - // TODO: Color should be normalized var geometry = new Geometry({ attributes : { color : new GeometryAttribute({ componentDatatype : ComponentDatatype.UNSIGNED_BYTE, componentsPerAttribute : 4, + normalize : true, values : [255, 0, 0, 255, 0, 255, 0, 255] }), position : new GeometryAttribute({ @@ -442,8 +442,6 @@ defineSuite([ }); it('creates a custom interleaved vertex', function() { - // TODO: Color should be normalized - var geometry = new Geometry({ attributes : { position : new GeometryAttribute({ @@ -454,6 +452,7 @@ defineSuite([ color : new GeometryAttribute({ componentDatatype : ComponentDatatype.UNSIGNED_BYTE, componentsPerAttribute : 3, + normalize : true, values : [255, 0, 0, 0, 255, 0] }), normal : new GeometryAttribute({ From ebe0774a696539cfcaf8ca58746b3ab914a2b587 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Thu, 13 Jun 2013 14:59:24 -0400 Subject: [PATCH 174/306] A bit more doc --- Source/Core/BoundingSphere.js | 12 ++++- Source/Core/GeometryAttribute.js | 79 ++++++++++++++++++++++++++++++-- 2 files changed, 86 insertions(+), 5 deletions(-) diff --git a/Source/Core/BoundingSphere.js b/Source/Core/BoundingSphere.js index 38e457029434..e61156df6e42 100644 --- a/Source/Core/BoundingSphere.js +++ b/Source/Core/BoundingSphere.js @@ -522,9 +522,19 @@ define([ }; /** - * DOC_TBA + * Creaates a bounding sphere encompassing an ellipsoid. + * + * @memberof BoundingSphere + * + * @param {Ellipsoid} ellipsoid The ellipsoid around which to create a bounding sphere. + * @param {BoundingSphere} [result] The object onto which to store the result. + * + * @return {BoundingSphere} The modified result parameter or a new BoundingSphere instance if none was provided. * * @exception {DeveloperError} ellipsoid is required. + * + * @example + * var boundingSphere = BoundingSphere.fromEllipsoid(ellipsoid); */ BoundingSphere.fromEllipsoid = function(ellipsoid, result) { if (typeof ellipsoid === 'undefined') { diff --git a/Source/Core/GeometryAttribute.js b/Source/Core/GeometryAttribute.js index 4274fad04da3..876e094a3aa4 100644 --- a/Source/Core/GeometryAttribute.js +++ b/Source/Core/GeometryAttribute.js @@ -10,27 +10,98 @@ define([ * * @alias GeometryAttribute * @constructor + * + * @example + * var geometry = new Geometry({ + * attributes : { + * position : new GeometryAttribute({ + * componentDatatype : ComponentDatatype.FLOAT, + * componentsPerAttribute : 3, + * values : [ + * 0.0, 0.0, 0.0, + * 7500000.0, 0.0, 0.0, + * 0.0, 7500000.0, 0.0 + * ] + * }) + * }, + * primitiveType : PrimitiveType.LINE_LOOP + * }); */ var GeometryAttribute = function(options) { options = defaultValue(options, defaultValue.EMPTY_OBJECT); /** - * DOC_TBA + * The datatype of each component in the attribute, e.g., individual elements in + * {@see GeometryAttribute#values}. + * + * @type ComponentDatatype + * + * @default undefined */ this.componentDatatype = options.componentDatatype; /** - * DOC_TBA + * A number between 1 and 4 that defines the number of components in an attributes. + * For example, a position attribute with x, y, and z components would have 3 as + * shown in the code example. + * + * @type Number + * + * @default undefined + * + * @example + * attribute.componentDatatype : ComponentDatatype.FLOAT, + * attribute.componentsPerAttribute : 3, + * attribute.values = new Float32Array([ + * 0.0, 0.0, 0.0, + * 7500000.0, 0.0, 0.0, + * 0.0, 7500000.0, 0.0 + * ]); */ this.componentsPerAttribute = options.componentsPerAttribute; /** - * DOC_TBA + * When true and componentDatatype is an integer format, + * indicate that the components should be mapped to the range [0, 1] (unsigned) + * or [-1, 1] (signed) when they are accessed as floating-point for rendering. + *

    + * This is commonly used when storing colors using {@ ComponentDatatype.UNSIGNED_BYTE}. + *

    + * + * @type Boolean + * + * @default false + * + * @example + * attribute.componentDatatype : ComponentDatatype.UNSIGNED_BYTE, + * attribute.componentsPerAttribute : 4, + * attribute.normalize = true; + * attribute.values = new Uint8Array([ + * Color.floatToByte(color.red) + * Color.floatToByte(color.green) + * Color.floatToByte(color.blue) + * Color.floatToByte(color.alpha) + * ]); */ this.normalize = defaultValue(options.normalize, false); /** - * DOC_TBA + * The values for the attributes stored in a typed array. In the code example, + * every three elements in values defines one attributes since + * componentsPerAttribute is 3. + * + * @type Array + * + * @default undefined + * + * @example + * attribute.componentDatatype : ComponentDatatype.FLOAT, + * attribute.componentsPerAttribute : 3, + * attribute.values = new Float32Array([ + * 0.0, 0.0, 0.0, + * 7500000.0, 0.0, 0.0, + * 0.0, 7500000.0, 0.0 + * ]); */ this.values = options.values; }; From 0e7303f028b63b7b20338fc8362d3db2a27c14dd Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 13 Jun 2013 18:56:27 -0400 Subject: [PATCH 175/306] Create short or int array for indices depending on the number of vertices. --- Source/Core/BoxGeometry.js | 4 ++-- Source/Core/EllipseGeometry.js | 7 +++++- Source/Core/EllipsoidGeometry.js | 6 +++++ Source/Core/ExtentGeometry.js | 8 ++++++- Source/Core/Geometry.js | 3 ++- Source/Core/GeometryPipeline.js | 38 +++++++++++++++++++++++++++----- Source/Core/WallGeometry.js | 8 ++++++- 7 files changed, 62 insertions(+), 12 deletions(-) diff --git a/Source/Core/BoxGeometry.js b/Source/Core/BoxGeometry.js index acd6a7418916..252eb297e41f 100644 --- a/Source/Core/BoxGeometry.js +++ b/Source/Core/BoxGeometry.js @@ -299,7 +299,7 @@ define([ } // 12 triangles: 6 faces, 2 triangles each. - indexList = new Uint32Array(6 * 2 * 3); + indexList = new Uint16Array(6 * 2 * 3); // +z face indexList[0] = 0; indexList[1] = 1; indexList[2] = 2; @@ -344,7 +344,7 @@ define([ }); // 12 triangles: 6 faces, 2 triangles each. - indexList = new Uint32Array(6 * 2 * 3); + indexList = new Uint16Array(6 * 2 * 3); // plane z = corner.Z indexList[0] = 4; indexList[1] = 5; indexList[2] = 6; diff --git a/Source/Core/EllipseGeometry.js b/Source/Core/EllipseGeometry.js index 8c72d1751b9a..c79897f4c5c5 100644 --- a/Source/Core/EllipseGeometry.js +++ b/Source/Core/EllipseGeometry.js @@ -422,7 +422,12 @@ define([ } indices.length = indicesIndex; - indices = new Uint32Array(indices); + + if (positions.length / 3 > 64 * 1024) { + indices = new Uint32Array(indices); + } else { + indices = new Uint16Array(indices); + } /** * An object containing {@link GeometryAttribute} properties named after each of the diff --git a/Source/Core/EllipsoidGeometry.js b/Source/Core/EllipsoidGeometry.js index c4fcbf183753..133351c96572 100644 --- a/Source/Core/EllipsoidGeometry.js +++ b/Source/Core/EllipsoidGeometry.js @@ -303,6 +303,12 @@ define([ } } + if (length > 64 * 1024) { + indices = new Uint32Array(indices); + } else { + indices = new Uint16Array(indices); + } + /** * An object containing {@link GeometryAttribute} properties named after each of the * true values of the {@link VertexFormat} option. diff --git a/Source/Core/ExtentGeometry.js b/Source/Core/ExtentGeometry.js index 76929bd4d32d..488556136872 100644 --- a/Source/Core/ExtentGeometry.js +++ b/Source/Core/ExtentGeometry.js @@ -230,7 +230,13 @@ define([ } var indicesSize = 6 * (width - 1) * (height - 1); - var indices = new Uint32Array(indicesSize); + var indices; + if (size > 64 * 1024) { + indices = new Uint32Array(indicesSize); + } else { + indices = new Uint16Array(indicesSize); + } + var index = 0; var indicesIndex = 0; for ( var i = 0; i < height - 1; ++i) { diff --git a/Source/Core/Geometry.js b/Source/Core/Geometry.js index f62af07560a9..af8bcd85fdc0 100644 --- a/Source/Core/Geometry.js +++ b/Source/Core/Geometry.js @@ -180,7 +180,8 @@ define([ result.attributes = newAttributes; if (typeof geometry.indexList !== 'undefined') { - result.indexList = new Uint32Array(geometry.indexList); + var sourceValues = geometry.indexList; + result.indexList = sourceValues.constructor(sourceValues); } else { result.indexList = undefined; } diff --git a/Source/Core/GeometryPipeline.js b/Source/Core/GeometryPipeline.js index 45f879a669a5..55530843f71f 100644 --- a/Source/Core/GeometryPipeline.js +++ b/Source/Core/GeometryPipeline.js @@ -56,7 +56,14 @@ define([ function trianglesToLines(triangles) { var count = triangles.length; - var lines = new Uint32Array((count / 3) * 6); + var size = (count / 3) * 6; + var lines; + if (count > 64 * 1024) { + lines = new Uint32Array(size); + } else { + lines = new Uint16Array(size); + } + var index = 0; for ( var i = 0; i < count; i += 3, index += 6) { addTriangle(lines, index, triangles[i], triangles[i + 1], triangles[i + 2]); @@ -68,7 +75,13 @@ define([ function triangleStripToLines(triangles) { var count = triangles.length; if (count >= 3) { - var lines = new Uint32Array((count - 2) * 6); + var size = (count - 2) * 6; + var lines; + if (count > 64 * 1024) { + lines = new Uint32Array(size); + } else { + lines = new Uint16Array(size); + } addTriangle(lines, 0, triangles[0], triangles[1], triangles[2]); var index = 6; @@ -80,13 +93,20 @@ define([ return lines; } - return []; + return new Uint16Array(); } function triangleFanToLines(triangles) { if (triangles.length > 0) { var count = triangles.length - 1; - var lines = new Uint32Array((count - 1) * 6); + var size = (count - 1) * 6; + var lines; + if (count > 64 * 1024) { + lines = new Uint32Array(size); + } else { + lines = new Uint16Array(size); + } + var base = triangles[0]; var index = 0; for ( var i = 1; i < count; ++i, index += 6) { @@ -96,7 +116,7 @@ define([ return lines; } - return []; + return new Uint16Array(); } /** @@ -213,7 +233,13 @@ define([ // Construct cross reference and reorder indices var indicesIn = indexList; var numIndices = indicesIn.length; - var indicesOut = new Uint32Array(numIndices); + var indicesOut; + if (numVertices > 64 * 1024) { + indicesOut = new Uint32Array(numIndices); + } else { + indicesOut = new Uint16Array(numIndices); + } + var intoIndicesIn = 0; var intoIndicesOut = 0; var nextIndex = 0; diff --git a/Source/Core/WallGeometry.js b/Source/Core/WallGeometry.js index 5fb14d659243..508107dadaaf 100644 --- a/Source/Core/WallGeometry.js +++ b/Source/Core/WallGeometry.js @@ -255,8 +255,14 @@ define([ // C (i) D (i+2) F // + length = size; size -= 2; - var indices = new Uint32Array(size * 3); + var indices; + if (length > 64 * 1024) { + indices = new Uint32Array(size * 3); + } else { + indices = new Uint16Array(size * 3); + } var j = 0; for (i = 0; i < size; i += 2) { From 2653a8974366a7dc345aee9ed7991fa67e25ed53 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 13 Jun 2013 20:01:38 -0400 Subject: [PATCH 176/306] Add new double component datatype and modify primitives to use it. --- Apps/CesiumViewer/CesiumViewer.js | 14 ++++++------- Source/Core/BoxGeometry.js | 2 +- Source/Core/ComponentDatatype.js | 20 +++++++++++++++++- Source/Core/EllipseGeometry.js | 2 +- Source/Core/EllipsoidGeometry.js | 2 +- Source/Core/ExtentGeometry.js | 2 +- Source/Core/Geometry.js | 2 +- Source/Core/GeometryPipeline.js | 11 +++++----- Source/Core/PolygonGeometry.js | 6 +++++- Source/Core/WallGeometry.js | 2 +- Source/Renderer/Context.js | 35 ++++++++++++++++++++++++------- 11 files changed, 69 insertions(+), 29 deletions(-) diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index 4074fa17bdd2..68502e6cf8c2 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -285,16 +285,16 @@ define([ geometry : new Geometry({ attributes : { position : new GeometryAttribute({ - componentDatatype : ComponentDatatype.FLOAT, + componentDatatype : ComponentDatatype.DOUBLE, componentsPerAttribute : 3, - values : [ + values : new Float64Array([ 0.0, 0.0, 2000000.0, 7500000.0, 0.0, 2000000.0, 0.0, 7500000.0, 2000000.0 - ] + ]) }) }, - indexList : [0, 1, 1, 2, 2, 0], + indexList : new Uint16Array([0, 1, 1, 2, 2, 0]), primitiveType : PrimitiveType.LINES }), pickData : 'customWithIndices' @@ -308,13 +308,13 @@ define([ geometry : new Geometry({ attributes : { position : new GeometryAttribute({ - componentDatatype : ComponentDatatype.FLOAT, + componentDatatype : ComponentDatatype.DOUBLE, componentsPerAttribute : 3, - values : [ + values : new Float64Array([ 0.0, 0.0, 0.0, 7500000.0, 0.0, 0.0, 0.0, 7500000.0, 0.0 - ] + ]) }) }, primitiveType : PrimitiveType.LINE_LOOP diff --git a/Source/Core/BoxGeometry.js b/Source/Core/BoxGeometry.js index 252eb297e41f..c33a532145b5 100644 --- a/Source/Core/BoxGeometry.js +++ b/Source/Core/BoxGeometry.js @@ -108,7 +108,7 @@ define([ positions[69] = min.x; positions[70] = min.y; positions[71] = max.z; attributes.position = new GeometryAttribute({ - componentDatatype : ComponentDatatype.FLOAT, + componentDatatype : ComponentDatatype.DOUBLE, componentsPerAttribute : 3, values : positions }); diff --git a/Source/Core/ComponentDatatype.js b/Source/Core/ComponentDatatype.js index 77f40103f4de..01b1c96997f4 100644 --- a/Source/Core/ComponentDatatype.js +++ b/Source/Core/ComponentDatatype.js @@ -104,6 +104,23 @@ define(['./Enumeration'], function(Enumeration) { return new Float32Array(buffer, byteOffset); }; + /** + * DOC_TBA + * + * @constant + * @type {Enumeration} + * @memberOf ComponentDatatype + */ + ComponentDatatype.DOUBLE = new Enumeration(0x140A, 'DOUBLE'); + ComponentDatatype.DOUBLE.sizeInBytes = Float64Array.BYTES_PER_ELEMENT; + ComponentDatatype.DOUBLE.createTypedArray = function(valuesOrLength) { + return new Float64Array(valuesOrLength); + }; + + ComponentDatatype.DOUBLE.createArrayBufferView = function(buffer, byteOffset) { + return new Float64Array(buffer, byteOffset); + }; + /** * DOC_TBA */ @@ -112,7 +129,8 @@ define(['./Enumeration'], function(Enumeration) { (componentDatatype === ComponentDatatype.UNSIGNED_BYTE) || (componentDatatype === ComponentDatatype.SHORT) || (componentDatatype === ComponentDatatype.UNSIGNED_SHORT) || - (componentDatatype === ComponentDatatype.FLOAT)); + (componentDatatype === ComponentDatatype.FLOAT) || + (componentDatatype === ComponentDatatype.DOUBLE)); }; return ComponentDatatype; diff --git a/Source/Core/EllipseGeometry.js b/Source/Core/EllipseGeometry.js index c79897f4c5c5..2f74ee351fc8 100644 --- a/Source/Core/EllipseGeometry.js +++ b/Source/Core/EllipseGeometry.js @@ -305,7 +305,7 @@ define([ if (vertexFormat.position) { attributes.position = new GeometryAttribute({ - componentDatatype : ComponentDatatype.FLOAT, + componentDatatype : ComponentDatatype.DOUBLE, componentsPerAttribute : 3, values : positions }); diff --git a/Source/Core/EllipsoidGeometry.js b/Source/Core/EllipsoidGeometry.js index 133351c96572..1fe7c8874a10 100644 --- a/Source/Core/EllipsoidGeometry.js +++ b/Source/Core/EllipsoidGeometry.js @@ -224,7 +224,7 @@ define([ } attributes.position = new GeometryAttribute({ - componentDatatype : ComponentDatatype.FLOAT, + componentDatatype : ComponentDatatype.DOUBLE, componentsPerAttribute : 3, values : flattenedPositions }); diff --git a/Source/Core/ExtentGeometry.js b/Source/Core/ExtentGeometry.js index 488556136872..52082266d352 100644 --- a/Source/Core/ExtentGeometry.js +++ b/Source/Core/ExtentGeometry.js @@ -260,7 +260,7 @@ define([ if (vertexFormat.position) { attributes.position = new GeometryAttribute({ - componentDatatype : ComponentDatatype.FLOAT, + componentDatatype : ComponentDatatype.DOUBLE, componentsPerAttribute : 3, values : positions }); diff --git a/Source/Core/Geometry.js b/Source/Core/Geometry.js index af8bcd85fdc0..4a199aae36bd 100644 --- a/Source/Core/Geometry.js +++ b/Source/Core/Geometry.js @@ -181,7 +181,7 @@ define([ if (typeof geometry.indexList !== 'undefined') { var sourceValues = geometry.indexList; - result.indexList = sourceValues.constructor(sourceValues); + result.indexList = new sourceValues.constructor(sourceValues); } else { result.indexList = undefined; } diff --git a/Source/Core/GeometryPipeline.js b/Source/Core/GeometryPipeline.js index 55530843f71f..45453f264023 100644 --- a/Source/Core/GeometryPipeline.js +++ b/Source/Core/GeometryPipeline.js @@ -539,7 +539,7 @@ define([ * * @exception {DeveloperError} geometry is required. * @exception {DeveloperError} geometry must have attribute matching the attributeName argument. - * @exception {DeveloperError} The attribute componentDatatype must be ComponentDatatype.FLOAT. + * @exception {DeveloperError} The attribute componentDatatype must be ComponentDatatype.FLOAT or ComponentDatatype.DOUBLE. * * @example * geometry = GeometryPipeline.encodeAttribute(geometry, 'position3D', 'position3DHigh', 'position3DLow'); @@ -561,8 +561,8 @@ define([ throw new DeveloperError('geometry must have attribute matching the attributeName argument: ' + attributeName + '.'); } - if (attribute.componentDatatype !== ComponentDatatype.FLOAT) { - throw new DeveloperError('The attribute componentDatatype must be ComponentDatatype.FLOAT.'); + if (attribute.componentDatatype !== ComponentDatatype.FLOAT && attribute.componentDatatype !== ComponentDatatype.DOUBLE) { + throw new DeveloperError('The attribute componentDatatype must be ComponentDatatype.FLOAT or ComponentDatatype.DOUBLE.'); } var values = attribute.values; @@ -576,16 +576,15 @@ define([ lowValues[i] = encodedResult.low; } - var componentDatatype = attribute.componentDatatype; var componentsPerAttribute = attribute.componentsPerAttribute; geometry.attributes[attributeHighName] = new GeometryAttribute({ - componentDatatype : componentDatatype, + componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : componentsPerAttribute, values : highValues }); geometry.attributes[attributeLowName] = new GeometryAttribute({ - componentDatatype : componentDatatype, + componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : componentsPerAttribute, values : lowValues }); diff --git a/Source/Core/PolygonGeometry.js b/Source/Core/PolygonGeometry.js index 5cf1a7e1dd4f..63f8ef7062b4 100644 --- a/Source/Core/PolygonGeometry.js +++ b/Source/Core/PolygonGeometry.js @@ -285,7 +285,11 @@ define([ var attributes = {}; if (vertexFormat.position) { - attributes.position = geometry.attributes.position; + attributes.position = new GeometryAttribute({ + componentDatatype : ComponentDatatype.DOUBLE, + componentsPerAttribute : 3, + values : new Float64Array(geometry.attributes.position.values) + }); } if (vertexFormat.st || vertexFormat.normal || vertexFormat.tangent || vertexFormat.binormal) { diff --git a/Source/Core/WallGeometry.js b/Source/Core/WallGeometry.js index 508107dadaaf..5a9b1ade0e08 100644 --- a/Source/Core/WallGeometry.js +++ b/Source/Core/WallGeometry.js @@ -202,7 +202,7 @@ define([ if (vertexFormat.position) { attributes.position = new GeometryAttribute({ - componentDatatype : ComponentDatatype.FLOAT, + componentDatatype : ComponentDatatype.DOUBLE, componentsPerAttribute : 3, values : positions }); diff --git a/Source/Renderer/Context.js b/Source/Renderer/Context.js index 1209c6de3986..5022b5da30eb 100644 --- a/Source/Renderer/Context.js +++ b/Source/Renderer/Context.js @@ -4,6 +4,7 @@ define([ '../Core/DeveloperError', '../Core/destroyObject', '../Core/Color', + '../Core/ComponentDatatype', '../Core/IndexDatatype', '../Core/RuntimeError', '../Core/PrimitiveType', @@ -37,6 +38,7 @@ define([ DeveloperError, destroyObject, Color, + ComponentDatatype, IndexDatatype, RuntimeError, PrimitiveType, @@ -2199,8 +2201,13 @@ define([ var names = []; for (name in attributes) { // Attribute needs to have per-vertex values; not a constant value for all vertices. - if (attributes.hasOwnProperty(name) && attributes[name].values) { + if (attributes.hasOwnProperty(name) && typeof attributes[name].values !== 'undefined') { names.push(name); + + if (attributes[name].componentDatatype === ComponentDatatype.DOUBLE) { + attributes[name].componentDatatype = ComponentDatatype.FLOAT; + attributes[name].values = ComponentDatatype.FLOAT.createTypedArray(attributes[name].values); + } } } @@ -2364,18 +2371,19 @@ define([ var bufferUsage = defaultValue(ca.bufferUsage, BufferUsage.DYNAMIC_DRAW); var attributeIndices = defaultValue(ca.attributeIndices, defaultValue.EMPTY_OBJECT); - var interleave = ca.vertexLayout && (ca.vertexLayout === VertexLayout.INTERLEAVED); + var interleave = (typeof ca.vertexLayout !== 'undefined') && (ca.vertexLayout === VertexLayout.INTERLEAVED); var name; var attribute; + var vertexBuffer; var vaAttributes = []; var attributes = geometry.attributes; if (interleave) { // Use a single vertex buffer with interleaved vertices. var interleavedAttributes = interleaveAttributes(attributes); - if (interleavedAttributes) { - var vertexBuffer = this.createVertexBuffer(interleavedAttributes.buffer, bufferUsage); + if (typeof interleavedAttributes !== 'undefined') { + vertexBuffer = this.createVertexBuffer(interleavedAttributes.buffer, bufferUsage); var offsetsInBytes = interleavedAttributes.offsetsInBytes; var strideInBytes = interleavedAttributes.vertexSizeInBytes; @@ -2383,7 +2391,7 @@ define([ if (attributes.hasOwnProperty(name)) { attribute = attributes[name]; - if (attribute.values) { + if (typeof attribute.values !== 'undefined') { // Common case: per-vertex attributes vaAttributes.push({ index : attributeIndices[name], @@ -2411,11 +2419,22 @@ define([ for (name in attributes) { if (attributes.hasOwnProperty(name)) { attribute = attributes[name]; + + var componentDatatype = attribute.componentDatatype; + if (componentDatatype === ComponentDatatype.DOUBLE) { + componentDatatype = ComponentDatatype.FLOAT; + } + + vertexBuffer = undefined; + if (typeof attribute.values !== 'undefined') { + vertexBuffer = this.createVertexBuffer(componentDatatype.createTypedArray(attribute.values), bufferUsage); + } + vaAttributes.push({ index : attributeIndices[name], - vertexBuffer : attribute.values ? this.createVertexBuffer(attribute.componentDatatype.createTypedArray(attribute.values), bufferUsage) : undefined, - value : attribute.value ? attribute.value : undefined, - componentDatatype : attribute.componentDatatype, + vertexBuffer : vertexBuffer, + value : attribute.value, + componentDatatype : componentDatatype, componentsPerAttribute : attribute.componentsPerAttribute, normalize : attribute.normalize }); From cbe86420f45fd53ff0611f24a513bb06cc698f5e Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 13 Jun 2013 20:07:20 -0400 Subject: [PATCH 177/306] Decrease number of partitions when computing ellipsoid for tangent/binormal test to increase test performance. --- Specs/Core/GeometryPipelineSpec.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Specs/Core/GeometryPipelineSpec.js b/Specs/Core/GeometryPipelineSpec.js index fad0b9f8cb69..255a91967337 100644 --- a/Specs/Core/GeometryPipelineSpec.js +++ b/Specs/Core/GeometryPipelineSpec.js @@ -982,19 +982,22 @@ defineSuite([ }); it ('GeometryPipeline.computeBinormalAndTangent computes tangent and binormal for an EllipsoidGeometry', function() { + var numberOfPartitions = 10; var geometry = new EllipsoidGeometry({ vertexFormat : new VertexFormat({ position : true, normal : true, st : true - }) + }), + numberOfPartitions : numberOfPartitions }); geometry = GeometryPipeline.computeBinormalAndTangent(geometry); var actualTangents = geometry.attributes.tangent.values; var actualBinormals = geometry.attributes.binormal.values; var expectedGeometry = new EllipsoidGeometry({ - vertexFormat: VertexFormat.ALL + vertexFormat: VertexFormat.ALL, + numberOfPartitions : numberOfPartitions }); var expectedTangents = expectedGeometry.attributes.tangent.values; var expectedBinormals = expectedGeometry.attributes.binormal.values; @@ -1002,7 +1005,7 @@ defineSuite([ expect(actualTangents.length).toEqual(expectedTangents.length); expect(actualBinormals.length).toEqual(expectedBinormals.length); - for (var i = 1000; i < 12000; i += 3) { + for (var i = 300; i < 500; i += 3) { var actual = Cartesian3.fromArray(actualTangents, i); var expected = Cartesian3.fromArray(expectedTangents, i); expect(actual).toEqualEpsilon(expected, CesiumMath.EPSILON1); From c92b0c2fe9afc8df80025f640ed60d7b53479eec Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 13 Jun 2013 20:46:20 -0400 Subject: [PATCH 178/306] Start adding support for 2D and columbus view. --- Apps/CesiumViewer/CesiumViewer.js | 4 ++- Source/Core/GeometryPipeline.js | 7 +++--- Source/Scene/Primitive.js | 10 +++++--- .../Appearances/DefaultAppearanceVS.glsl | 23 ++++++++++++++--- .../EllipsoidSurfaceAppearanceVS.glsl | 25 ++++++++++++++++--- .../PerInstanceColorAppearanceVS.glsl | 23 ++++++++++++++--- 6 files changed, 74 insertions(+), 18 deletions(-) diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index 68502e6cf8c2..a93be555588f 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -198,7 +198,7 @@ define([ appearance :appearance, vertexCacheOptimize : false, releasegeometryInstances : true, - transformToWorldCoordinates : false + //transformToWorldCoordinates : false })); var polygonGeometry = new GeometryInstance({ @@ -281,6 +281,7 @@ define([ }) })); + /* var customWithIndices = new GeometryInstance({ geometry : new Geometry({ attributes : { @@ -325,6 +326,7 @@ define([ geometryInstances : customWithoutIndices, appearance : new Appearance() })); + */ var handler = new ScreenSpaceEventHandler(scene.getCanvas()); handler.setInputAction( diff --git a/Source/Core/GeometryPipeline.js b/Source/Core/GeometryPipeline.js index 45453f264023..f0128bbd75a8 100644 --- a/Source/Core/GeometryPipeline.js +++ b/Source/Core/GeometryPipeline.js @@ -491,7 +491,7 @@ define([ // Project original positions to 2D. var wgs84Positions = geometry.attributes.position.values; - var projectedPositions = new Float64Array(2 * wgs84Positions.length / 3); + var projectedPositions = new Float64Array(wgs84Positions.length); var index = 0; for ( var i = 0; i < wgs84Positions.length; i += 3) { @@ -501,6 +501,7 @@ define([ projectedPositions[index++] = projectedLonLat.x; projectedPositions[index++] = projectedLonLat.y; + projectedPositions[index++] = projectedLonLat.z; } // Rename original positions to WGS84 Positions. @@ -508,8 +509,8 @@ define([ // Replace original positions with 2D projected positions geometry.attributes.position2D = new GeometryAttribute({ - componentDatatype : ComponentDatatype.FLOAT, - componentsPerAttribute : 2, + componentDatatype : ComponentDatatype.DOUBLE, + componentsPerAttribute : 3, values : projectedPositions }); delete geometry.attributes.position; diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index eb3f3bb944b1..c283eb814688 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -417,8 +417,12 @@ define([ // Combine into single geometry for better rendering performance. var geometry = GeometryPipeline.combine(insts); - // Split position for GPU RTE - GeometryPipeline.encodeAttribute(geometry, 'position', 'positionHigh', 'positionLow'); + // Compute 2D positions + GeometryPipeline.projectTo2D(geometry); + + // Split 3D and 2D position for GPU RTE + GeometryPipeline.encodeAttribute(geometry, 'position3D', 'position3DHigh', 'position3DLow'); + GeometryPipeline.encodeAttribute(geometry, 'position2D', 'position2DHigh', 'position2DLow'); if (!context.getElementIndexUint()) { // Break into multiple geometries to fit within unsigned short indices if needed @@ -434,10 +438,8 @@ define([ */ Primitive.prototype.update = function(context, frameState, commandList) { if (!this.show || - (frameState.mode !== SceneMode.SCENE3D) || ((typeof this.geometryInstances === 'undefined') && (this._va.length === 0)) || (typeof this.appearance === 'undefined')) { -// TODO: support Columbus view and 2D return; } diff --git a/Source/Shaders/Appearances/DefaultAppearanceVS.glsl b/Source/Shaders/Appearances/DefaultAppearanceVS.glsl index b53c37853f7a..27a5bf96e6e7 100644 --- a/Source/Shaders/Appearances/DefaultAppearanceVS.glsl +++ b/Source/Shaders/Appearances/DefaultAppearanceVS.glsl @@ -1,5 +1,7 @@ -attribute vec3 positionHigh; -attribute vec3 positionLow; +attribute vec3 position3DHigh; +attribute vec3 position3DLow; +attribute vec3 position2DHigh; +attribute vec3 position2DLow; attribute vec3 normal; attribute vec3 tangent; attribute vec3 binormal; @@ -15,7 +17,22 @@ varying vec4 czm_pickColor; void main() { - vec4 p = czm_translateRelativeToEye(positionHigh, positionLow); + vec4 p; + if (czm_morphTime == 1.0) + { + p = czm_translateRelativeToEye(position3DHigh, position3DLow); + } + else if (czm_morphTime == 0.0) + { + p = czm_translateRelativeToEye(position2DHigh.zxy, position2DLow.zxy); + } + else + { + p = czm_columbusViewMorph( + czm_translateRelativeToEye(position2DHigh.zxy, position2DLow.zxy), + czm_translateRelativeToEye(position3DHigh, position3DLow), + czm_morphTime); + } v_positionEC = (czm_modelViewRelativeToEye * p).xyz; // position in eye coordinates v_normalEC = czm_normal * normal; // normal in eye coordinates diff --git a/Source/Shaders/Appearances/EllipsoidSurfaceAppearanceVS.glsl b/Source/Shaders/Appearances/EllipsoidSurfaceAppearanceVS.glsl index b33700b32729..6acd725fd6d0 100644 --- a/Source/Shaders/Appearances/EllipsoidSurfaceAppearanceVS.glsl +++ b/Source/Shaders/Appearances/EllipsoidSurfaceAppearanceVS.glsl @@ -1,5 +1,7 @@ -attribute vec3 positionHigh; -attribute vec3 positionLow; +attribute vec3 position3DHigh; +attribute vec3 position3DLow; +attribute vec3 position2DHigh; +attribute vec3 position2DLow; attribute vec2 st; attribute vec4 pickColor; @@ -10,9 +12,24 @@ varying vec4 czm_pickColor; void main() { - vec4 p = czm_translateRelativeToEye(positionHigh, positionLow); + vec4 p; + if (czm_morphTime == 1.0) + { + p = czm_translateRelativeToEye(position3DHigh, position3DLow); + } + else if (czm_morphTime == 0.0) + { + p = czm_translateRelativeToEye(position2DHigh.zxy, position2DLow.zxy); + } + else + { + p = czm_columbusViewMorph( + czm_translateRelativeToEye(position2DHigh.zxy, position2DLow.zxy), + czm_translateRelativeToEye(position3DHigh, position3DLow), + czm_morphTime); + } - v_positionMC = positionHigh + positionLow; // position in model coordinates + v_positionMC = position3DHigh + position3DLow; // position in model coordinates v_positionEC = (czm_modelViewRelativeToEye * p).xyz; // position in eye coordinates v_st = st; czm_pickColor = pickColor; diff --git a/Source/Shaders/Appearances/PerInstanceColorAppearanceVS.glsl b/Source/Shaders/Appearances/PerInstanceColorAppearanceVS.glsl index 0226303cb52e..67b3010e16cb 100644 --- a/Source/Shaders/Appearances/PerInstanceColorAppearanceVS.glsl +++ b/Source/Shaders/Appearances/PerInstanceColorAppearanceVS.glsl @@ -1,5 +1,7 @@ -attribute vec3 positionHigh; -attribute vec3 positionLow; +attribute vec3 position3DHigh; +attribute vec3 position3DLow; +attribute vec3 position2DHigh; +attribute vec3 position2DLow; attribute vec3 normal; attribute vec4 color; attribute vec4 pickColor; @@ -11,7 +13,22 @@ varying vec4 czm_pickColor; void main() { - vec4 p = czm_translateRelativeToEye(positionHigh, positionLow); + vec4 p; + if (czm_morphTime == 1.0) + { + p = czm_translateRelativeToEye(position3DHigh, position3DLow); + } + else if (czm_morphTime == 0.0) + { + p = czm_translateRelativeToEye(position2DHigh.zxy, position2DLow.zxy); + } + else + { + p = czm_columbusViewMorph( + czm_translateRelativeToEye(position2DHigh.zxy, position2DLow.zxy), + czm_translateRelativeToEye(position3DHigh, position3DLow), + czm_morphTime); + } v_positionEC = (czm_modelViewRelativeToEye * p).xyz; // position in eye coordinates v_normalEC = czm_normal * normal; // normal in eye coordinates From e7d02361cb181d84a511e2d20eda475fe4cf0b6e Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Fri, 14 Jun 2013 08:45:37 -0400 Subject: [PATCH 179/306] Cleanup typed array allocation --- Source/Core/EllipseGeometry.js | 12 +++------- Source/Core/EllipsoidGeometry.js | 10 +++----- Source/Core/ExtentGeometry.js | 9 +++---- Source/Core/GeometryPipeline.js | 40 ++++++++------------------------ Source/Core/IndexDatatype.js | 33 +++++++++++++++++++++++++- Source/Core/WallGeometry.js | 9 +++---- 6 files changed, 54 insertions(+), 59 deletions(-) diff --git a/Source/Core/EllipseGeometry.js b/Source/Core/EllipseGeometry.js index 2f74ee351fc8..308f484aff12 100644 --- a/Source/Core/EllipseGeometry.js +++ b/Source/Core/EllipseGeometry.js @@ -4,6 +4,7 @@ define([ './BoundingSphere', './Cartesian3', './ComponentDatatype', + './IndexDatatype', './DeveloperError', './Ellipsoid', './GeometryAttribute', @@ -17,6 +18,7 @@ define([ BoundingSphere, Cartesian3, ComponentDatatype, + IndexDatatype, DeveloperError, Ellipsoid, GeometryAttribute, @@ -421,14 +423,6 @@ define([ indices[indicesIndex++] = positionIndex++; } - indices.length = indicesIndex; - - if (positions.length / 3 > 64 * 1024) { - indices = new Uint32Array(indices); - } else { - indices = new Uint16Array(indices); - } - /** * An object containing {@link GeometryAttribute} properties named after each of the * true values of the {@link VertexFormat} option. @@ -444,7 +438,7 @@ define([ * * @type Array */ - this.indexList = indices; + this.indexList = IndexDatatype.createTypedArray(positions.length / 3, indices); /** * The type of primitives in the geometry. For this geometry, it is {@link PrimitiveType.TRIANGLES}. diff --git a/Source/Core/EllipsoidGeometry.js b/Source/Core/EllipsoidGeometry.js index 1fe7c8874a10..ea886ccaf9f7 100644 --- a/Source/Core/EllipsoidGeometry.js +++ b/Source/Core/EllipsoidGeometry.js @@ -6,6 +6,7 @@ define([ './Math', './Ellipsoid', './ComponentDatatype', + './IndexDatatype', './PrimitiveType', './BoundingSphere', './GeometryAttribute', @@ -17,6 +18,7 @@ define([ CesiumMath, Ellipsoid, ComponentDatatype, + IndexDatatype, PrimitiveType, BoundingSphere, GeometryAttribute, @@ -303,12 +305,6 @@ define([ } } - if (length > 64 * 1024) { - indices = new Uint32Array(indices); - } else { - indices = new Uint16Array(indices); - } - /** * An object containing {@link GeometryAttribute} properties named after each of the * true values of the {@link VertexFormat} option. @@ -324,7 +320,7 @@ define([ * * @type Array */ - this.indexList = indices; + this.indexList = IndexDatatype.createTypedArray(length, indices); /** * The type of primitives in the geometry. For this geometry, it is {@link PrimitiveType.TRIANGLES}. diff --git a/Source/Core/ExtentGeometry.js b/Source/Core/ExtentGeometry.js index 52082266d352..737e40e8e680 100644 --- a/Source/Core/ExtentGeometry.js +++ b/Source/Core/ExtentGeometry.js @@ -6,6 +6,7 @@ define([ './Cartesian3', './Cartographic', './ComponentDatatype', + './IndexDatatype', './DeveloperError', './Ellipsoid', './Extent', @@ -22,6 +23,7 @@ define([ Cartesian3, Cartographic, ComponentDatatype, + IndexDatatype, DeveloperError, Ellipsoid, Extent, @@ -230,12 +232,7 @@ define([ } var indicesSize = 6 * (width - 1) * (height - 1); - var indices; - if (size > 64 * 1024) { - indices = new Uint32Array(indicesSize); - } else { - indices = new Uint16Array(indicesSize); - } + var indices = IndexDatatype.createTypedArray(size, indicesSize); var index = 0; var indicesIndex = 0; diff --git a/Source/Core/GeometryPipeline.js b/Source/Core/GeometryPipeline.js index 45453f264023..69e4a33c13bf 100644 --- a/Source/Core/GeometryPipeline.js +++ b/Source/Core/GeometryPipeline.js @@ -10,6 +10,7 @@ define([ './Matrix4', './GeographicProjection', './ComponentDatatype', + './IndexDatatype', './PrimitiveType', './Tipsify', './BoundingSphere', @@ -26,6 +27,7 @@ define([ Matrix4, GeographicProjection, ComponentDatatype, + IndexDatatype, PrimitiveType, Tipsify, BoundingSphere, @@ -57,12 +59,7 @@ define([ function trianglesToLines(triangles) { var count = triangles.length; var size = (count / 3) * 6; - var lines; - if (count > 64 * 1024) { - lines = new Uint32Array(size); - } else { - lines = new Uint16Array(size); - } + var lines = IndexDatatype.createTypedArray(count, size); var index = 0; for ( var i = 0; i < count; i += 3, index += 6) { @@ -76,12 +73,7 @@ define([ var count = triangles.length; if (count >= 3) { var size = (count - 2) * 6; - var lines; - if (count > 64 * 1024) { - lines = new Uint32Array(size); - } else { - lines = new Uint16Array(size); - } + var lines = IndexDatatype.createTypedArray(count, size); addTriangle(lines, 0, triangles[0], triangles[1], triangles[2]); var index = 6; @@ -100,12 +92,7 @@ define([ if (triangles.length > 0) { var count = triangles.length - 1; var size = (count - 1) * 6; - var lines; - if (count > 64 * 1024) { - lines = new Uint32Array(size); - } else { - lines = new Uint16Array(size); - } + var lines = IndexDatatype.createTypedArray(count, size); var base = triangles[0]; var index = 0; @@ -233,12 +220,7 @@ define([ // Construct cross reference and reorder indices var indicesIn = indexList; var numIndices = indicesIn.length; - var indicesOut; - if (numVertices > 64 * 1024) { - indicesOut = new Uint32Array(numIndices); - } else { - indicesOut = new Uint16Array(numIndices); - } + var indicesOut = IndexDatatype.createTypedArray(numVertices, numIndices); var intoIndicesIn = 0; var intoIndicesOut = 0; @@ -815,12 +797,10 @@ define([ numberOfIndices += instances[i].geometry.indexList.length; } - var destIndices; - if (numberOfIndices < 60 * 1024) { - destIndices = new Uint16Array(numberOfIndices); - } else { - destIndices = new Uint32Array(numberOfIndices); - } + var numberOfVertices = Geometry.computeNumberOfVertices(new Geometry({ + attributes : attributes + })); + var destIndices = IndexDatatype.createTypedArray(numberOfVertices, numberOfIndices); var destOffset = 0; var offset = 0; diff --git a/Source/Core/IndexDatatype.js b/Source/Core/IndexDatatype.js index a3c0aa5fe801..398c916c43bf 100644 --- a/Source/Core/IndexDatatype.js +++ b/Source/Core/IndexDatatype.js @@ -1,5 +1,10 @@ /*global define*/ -define(['./Enumeration'], function(Enumeration) { +define([ + './Enumeration', + './DeveloperError' + ], function( + Enumeration, + DeveloperError) { "use strict"; /** @@ -45,5 +50,31 @@ define(['./Enumeration'], function(Enumeration) { (indexDatatype === IndexDatatype.UNSIGNED_INT)); }; + /** + * Creates a typed array that will store indices, using either + * or Uint32Array depending on the number of vertices. + * + * @param {Number} numberOfVertices Number of vertices that the indices will reference. + * @param {Any} indicesLengthOrArray Passed through to the typed array constructor. + * + * @return {Array} A Uint16Array or Uint32Array constructed with indicesLengthOrArray. + * + * @exception {DeveloperError} center is required. + * + * @example + * this.indexList = IndexDatatype.createTypedArray(positions.length / 3, numberOfIndices); + */ + IndexDatatype.createTypedArray = function(numberOfVertices, indicesLengthOrArray) { + if (typeof numberOfVertices !== 'undefined') { + throw new DeveloperError('numberOfVertices is required.'); + } + + if (numberOfVertices > 64 * 1024) { + return new Uint32Array(indicesLengthOrArray); + } + + return new Uint16Array(indicesLengthOrArray); + }; + return IndexDatatype; }); diff --git a/Source/Core/WallGeometry.js b/Source/Core/WallGeometry.js index 5a9b1ade0e08..fc5cef43a85e 100644 --- a/Source/Core/WallGeometry.js +++ b/Source/Core/WallGeometry.js @@ -5,6 +5,7 @@ define([ './Cartesian3', './Cartographic', './ComponentDatatype', + './IndexDatatype', './DeveloperError', './Ellipsoid', './EllipsoidTangentPlane', @@ -20,6 +21,7 @@ define([ Cartesian3, Cartographic, ComponentDatatype, + IndexDatatype, DeveloperError, Ellipsoid, EllipsoidTangentPlane, @@ -257,12 +259,7 @@ define([ length = size; size -= 2; - var indices; - if (length > 64 * 1024) { - indices = new Uint32Array(size * 3); - } else { - indices = new Uint16Array(size * 3); - } + var indices = IndexDatatype.createTypedArray(length, size * 3); var j = 0; for (i = 0; i < size; i += 2) { From b032c55dee6d60dcb025f418c5998939017ebf55 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Fri, 14 Jun 2013 09:26:42 -0400 Subject: [PATCH 180/306] Various FLOAT/DOUBLE fixes --- Source/Core/GeometryPipeline.js | 8 ++++---- Source/Core/IndexDatatype.js | 2 +- Source/Core/PolygonPipeline.js | 2 +- Specs/Core/GeometryPipelineSpec.js | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Source/Core/GeometryPipeline.js b/Source/Core/GeometryPipeline.js index 69e4a33c13bf..6881efdc878d 100644 --- a/Source/Core/GeometryPipeline.js +++ b/Source/Core/GeometryPipeline.js @@ -490,7 +490,7 @@ define([ // Replace original positions with 2D projected positions geometry.attributes.position2D = new GeometryAttribute({ - componentDatatype : ComponentDatatype.FLOAT, + componentDatatype : ComponentDatatype.DOUBLE, componentsPerAttribute : 2, values : projectedPositions }); @@ -521,7 +521,7 @@ define([ * * @exception {DeveloperError} geometry is required. * @exception {DeveloperError} geometry must have attribute matching the attributeName argument. - * @exception {DeveloperError} The attribute componentDatatype must be ComponentDatatype.FLOAT or ComponentDatatype.DOUBLE. + * @exception {DeveloperError} The attribute componentDatatype must be ComponentDatatype.DOUBLE. * * @example * geometry = GeometryPipeline.encodeAttribute(geometry, 'position3D', 'position3DHigh', 'position3DLow'); @@ -543,8 +543,8 @@ define([ throw new DeveloperError('geometry must have attribute matching the attributeName argument: ' + attributeName + '.'); } - if (attribute.componentDatatype !== ComponentDatatype.FLOAT && attribute.componentDatatype !== ComponentDatatype.DOUBLE) { - throw new DeveloperError('The attribute componentDatatype must be ComponentDatatype.FLOAT or ComponentDatatype.DOUBLE.'); + if (attribute.componentDatatype !== ComponentDatatype.DOUBLE) { + throw new DeveloperError('The attribute componentDatatype must be ComponentDatatype.DOUBLE.'); } var values = attribute.values; diff --git a/Source/Core/IndexDatatype.js b/Source/Core/IndexDatatype.js index 398c916c43bf..47bd277ab113 100644 --- a/Source/Core/IndexDatatype.js +++ b/Source/Core/IndexDatatype.js @@ -65,7 +65,7 @@ define([ * this.indexList = IndexDatatype.createTypedArray(positions.length / 3, numberOfIndices); */ IndexDatatype.createTypedArray = function(numberOfVertices, indicesLengthOrArray) { - if (typeof numberOfVertices !== 'undefined') { + if (typeof numberOfVertices === 'undefined') { throw new DeveloperError('numberOfVertices is required.'); } diff --git a/Source/Core/PolygonPipeline.js b/Source/Core/PolygonPipeline.js index 0227b05b2434..2786de7dfbf1 100644 --- a/Source/Core/PolygonPipeline.js +++ b/Source/Core/PolygonPipeline.js @@ -830,7 +830,7 @@ define([ return new Geometry({ attributes : { position : new GeometryAttribute({ - componentDatatype : ComponentDatatype.FLOAT, + componentDatatype : ComponentDatatype.DOUBLE, componentsPerAttribute : 3, values : flattenedPositions }) diff --git a/Specs/Core/GeometryPipelineSpec.js b/Specs/Core/GeometryPipelineSpec.js index 255a91967337..45062d89b312 100644 --- a/Specs/Core/GeometryPipelineSpec.js +++ b/Specs/Core/GeometryPipelineSpec.js @@ -504,7 +504,7 @@ defineSuite([ var geometry = new Geometry({ attributes : { position : new GeometryAttribute({ - componentDatatype : ComponentDatatype.FLOAT, + componentDatatype : ComponentDatatype.DOUBLE, componentsPerAttribute : 3, values : [c.x, c.y, c.z] }) From 3db7914a4a659c95a8aeb864eb98bb3937a9f98c Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Fri, 14 Jun 2013 10:09:07 -0400 Subject: [PATCH 181/306] Renamed indexList to indices --- Apps/CesiumViewer/CesiumViewer.js | 2 +- Source/Core/BoxGeometry.js | 56 ++++++------- Source/Core/CircleGeometry.js | 2 +- Source/Core/EllipseGeometry.js | 2 +- Source/Core/EllipsoidGeometry.js | 2 +- Source/Core/ExtentGeometry.js | 2 +- Source/Core/Geometry.js | 16 ++-- Source/Core/GeometryPipeline.js | 72 ++++++++-------- Source/Core/IndexDatatype.js | 2 +- Source/Core/PolygonGeometry.js | 2 +- Source/Core/PolygonPipeline.js | 2 +- Source/Core/WallGeometry.js | 2 +- Source/Renderer/Context.js | 8 +- Source/Scene/CentralBody.js | 2 +- Source/Scene/ImageryLayer.js | 2 +- Specs/Core/BoxGeometrySpec.js | 4 +- Specs/Core/CircleGeometrySpec.js | 4 +- Specs/Core/EllipseGeometrySpec.js | 4 +- Specs/Core/EllipsoidGeometrySpec.js | 4 +- Specs/Core/ExtentGeometrySpec.js | 8 +- Specs/Core/GeometryPipelineSpec.js | 102 +++++++++++------------ Specs/Core/PolygonGeometrySpec.js | 8 +- Specs/Core/PolygonPipelineSpec.js | 6 +- Specs/Core/WallGeometrySpec.js | 6 +- Specs/Renderer/VertexArrayFactorySpec.js | 4 +- 25 files changed, 162 insertions(+), 162 deletions(-) diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index 68502e6cf8c2..bca024d092ff 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -294,7 +294,7 @@ define([ ]) }) }, - indexList : new Uint16Array([0, 1, 1, 2, 2, 0]), + indices : new Uint16Array([0, 1, 1, 2, 2, 0]), primitiveType : PrimitiveType.LINES }), pickData : 'customWithIndices' diff --git a/Source/Core/BoxGeometry.js b/Source/Core/BoxGeometry.js index c33a532145b5..5d39a1b8deda 100644 --- a/Source/Core/BoxGeometry.js +++ b/Source/Core/BoxGeometry.js @@ -63,7 +63,7 @@ define([ var vertexFormat = defaultValue(options.vertexFormat, VertexFormat.DEFAULT); var attributes = {}; - var indexList; + var indices; var positions; if (vertexFormat !== VertexFormat.POSITION_ONLY) { @@ -299,31 +299,31 @@ define([ } // 12 triangles: 6 faces, 2 triangles each. - indexList = new Uint16Array(6 * 2 * 3); + indices = new Uint16Array(6 * 2 * 3); // +z face - indexList[0] = 0; indexList[1] = 1; indexList[2] = 2; - indexList[3] = 0; indexList[4] = 2; indexList[5] = 3; + indices[0] = 0; indices[1] = 1; indices[2] = 2; + indices[3] = 0; indices[4] = 2; indices[5] = 3; // -z face - indexList[6] = 4 + 2; indexList[7] = 4 + 1; indexList[8] = 4 + 0; - indexList[9] = 4 + 3; indexList[10] = 4 + 2; indexList[11] = 4 + 0; + indices[6] = 4 + 2; indices[7] = 4 + 1; indices[8] = 4 + 0; + indices[9] = 4 + 3; indices[10] = 4 + 2; indices[11] = 4 + 0; // +x face - indexList[12] = 8 + 0; indexList[13] = 8 + 1; indexList[14] = 8 + 2; - indexList[15] = 8 + 0; indexList[16] = 8 + 2; indexList[17] = 8 + 3; + indices[12] = 8 + 0; indices[13] = 8 + 1; indices[14] = 8 + 2; + indices[15] = 8 + 0; indices[16] = 8 + 2; indices[17] = 8 + 3; // -x face - indexList[18] = 12 + 2; indexList[19] = 12 + 1; indexList[20] = 12 + 0; - indexList[21] = 12 + 3; indexList[22] = 12 + 2; indexList[23] = 12 + 0; + indices[18] = 12 + 2; indices[19] = 12 + 1; indices[20] = 12 + 0; + indices[21] = 12 + 3; indices[22] = 12 + 2; indices[23] = 12 + 0; // +y face - indexList[24] = 16 + 2; indexList[25] = 16 + 1; indexList[26] = 16 + 0; - indexList[27] = 16 + 3; indexList[28] = 16 + 2; indexList[29] = 16 + 0; + indices[24] = 16 + 2; indices[25] = 16 + 1; indices[26] = 16 + 0; + indices[27] = 16 + 3; indices[28] = 16 + 2; indices[29] = 16 + 0; // -y face - indexList[30] = 20 + 0; indexList[31] = 20 + 1; indexList[32] = 20 + 2; - indexList[33] = 20 + 0; indexList[34] = 20 + 2; indexList[35] = 20 + 3; + indices[30] = 20 + 0; indices[31] = 20 + 1; indices[32] = 20 + 2; + indices[33] = 20 + 0; indices[34] = 20 + 2; indices[35] = 20 + 3; } else { // Positions only - no need to duplicate corner points positions = new Float64Array(8 * 3); @@ -344,31 +344,31 @@ define([ }); // 12 triangles: 6 faces, 2 triangles each. - indexList = new Uint16Array(6 * 2 * 3); + indices = new Uint16Array(6 * 2 * 3); // plane z = corner.Z - indexList[0] = 4; indexList[1] = 5; indexList[2] = 6; - indexList[3] = 4; indexList[4] = 6; indexList[5] = 7; + indices[0] = 4; indices[1] = 5; indices[2] = 6; + indices[3] = 4; indices[4] = 6; indices[5] = 7; // plane z = -corner.Z - indexList[6] = 1; indexList[7] = 0; indexList[8] = 3; - indexList[9] = 1; indexList[10] = 3; indexList[11] = 2; + indices[6] = 1; indices[7] = 0; indices[8] = 3; + indices[9] = 1; indices[10] = 3; indices[11] = 2; // plane x = corner.X - indexList[12] = 1; indexList[13] = 6; indexList[14] = 5; - indexList[15] = 1; indexList[16] = 2; indexList[17] = 6; + indices[12] = 1; indices[13] = 6; indices[14] = 5; + indices[15] = 1; indices[16] = 2; indices[17] = 6; // plane y = corner.Y - indexList[18] = 2; indexList[19] = 3; indexList[20] = 7; - indexList[21] = 2; indexList[22] = 7; indexList[23] = 6; + indices[18] = 2; indices[19] = 3; indices[20] = 7; + indices[21] = 2; indices[22] = 7; indices[23] = 6; // plane x = -corner.X - indexList[24] = 3; indexList[25] = 0; indexList[26] = 4; - indexList[27] = 3; indexList[28] = 4; indexList[29] = 7; + indices[24] = 3; indices[25] = 0; indices[26] = 4; + indices[27] = 3; indices[28] = 4; indices[29] = 7; // plane y = -corner.Y - indexList[30] = 0; indexList[31] = 1; indexList[32] = 5; - indexList[33] = 0; indexList[34] = 5; indexList[35] = 4; + indices[30] = 0; indices[31] = 1; indices[32] = 5; + indices[33] = 0; indices[34] = 5; indices[35] = 4; } /** @@ -386,7 +386,7 @@ define([ * * @type Array */ - this.indexList = indexList; + this.indices = indices; /** * The type of primitives in the geometry. For this geometry, it is {@link PrimitiveType.TRIANGLES}. diff --git a/Source/Core/CircleGeometry.js b/Source/Core/CircleGeometry.js index 46711c6473fa..aa906ec6ae5d 100644 --- a/Source/Core/CircleGeometry.js +++ b/Source/Core/CircleGeometry.js @@ -70,7 +70,7 @@ define([ * * @type Array */ - this.indexList = ellipseGeometry.indexList; + this.indices = ellipseGeometry.indices; /** * The type of primitives in the geometry. For this geometry, it is {@link PrimitiveType.TRIANGLES}. diff --git a/Source/Core/EllipseGeometry.js b/Source/Core/EllipseGeometry.js index 308f484aff12..a528d96ea14d 100644 --- a/Source/Core/EllipseGeometry.js +++ b/Source/Core/EllipseGeometry.js @@ -438,7 +438,7 @@ define([ * * @type Array */ - this.indexList = IndexDatatype.createTypedArray(positions.length / 3, indices); + this.indices = IndexDatatype.createTypedArray(positions.length / 3, indices); /** * The type of primitives in the geometry. For this geometry, it is {@link PrimitiveType.TRIANGLES}. diff --git a/Source/Core/EllipsoidGeometry.js b/Source/Core/EllipsoidGeometry.js index ea886ccaf9f7..21ca3146ca10 100644 --- a/Source/Core/EllipsoidGeometry.js +++ b/Source/Core/EllipsoidGeometry.js @@ -320,7 +320,7 @@ define([ * * @type Array */ - this.indexList = IndexDatatype.createTypedArray(length, indices); + this.indices = IndexDatatype.createTypedArray(length, indices); /** * The type of primitives in the geometry. For this geometry, it is {@link PrimitiveType.TRIANGLES}. diff --git a/Source/Core/ExtentGeometry.js b/Source/Core/ExtentGeometry.js index 737e40e8e680..7c9b84b70ef5 100644 --- a/Source/Core/ExtentGeometry.js +++ b/Source/Core/ExtentGeometry.js @@ -310,7 +310,7 @@ define([ * * @type Array */ - this.indexList = indices; + this.indices = indices; /** * The type of primitives in the geometry. For this geometry, it is {@link PrimitiveType.TRIANGLES}. diff --git a/Source/Core/Geometry.js b/Source/Core/Geometry.js index 4a199aae36bd..5c0f0276d276 100644 --- a/Source/Core/Geometry.js +++ b/Source/Core/Geometry.js @@ -41,7 +41,7 @@ define([ * values : positions * }) * }, - * indexList : [0, 1, 1, 2, 2, 0], + * indices : [0, 1, 1, 2, 2, 0], * primitiveType : PrimitiveType.LINES, * boundingSphere : BoundingSphere.fromVertices(positions) * }); @@ -115,9 +115,9 @@ define([ * @example * // Two triangles with shared vertices * geometry.primitiveType = PrimitiveType.TRIANGLES; - * geometry.indexList = new Uint16Array([0, 1, 2, 0, 2, 3]); + * geometry.indices = new Uint16Array([0, 1, 2, 0, 2, 3]); */ - this.indexList = options.indexList; + this.indices = options.indices; /** * The type of primitives in the geometry. This is most often {@link PrimitiveType.TRIANGLES}, @@ -130,7 +130,7 @@ define([ * @example * // Two triangles with shared vertices * geometry.primitiveType = PrimitiveType.TRIANGLES; - * geometry.indexList = new Uint16Array([0, 1, 2, 0, 2, 3]); + * geometry.indices = new Uint16Array([0, 1, 2, 0, 2, 3]); */ this.primitiveType = options.primitiveType; @@ -179,11 +179,11 @@ define([ } result.attributes = newAttributes; - if (typeof geometry.indexList !== 'undefined') { - var sourceValues = geometry.indexList; - result.indexList = new sourceValues.constructor(sourceValues); + if (typeof geometry.indices !== 'undefined') { + var sourceValues = geometry.indices; + result.indices = new sourceValues.constructor(sourceValues); } else { - result.indexList = undefined; + result.indices = undefined; } result.primitiveType = geometry.primitiveType; diff --git a/Source/Core/GeometryPipeline.js b/Source/Core/GeometryPipeline.js index 6881efdc878d..0069411cdca9 100644 --- a/Source/Core/GeometryPipeline.js +++ b/Source/Core/GeometryPipeline.js @@ -107,7 +107,7 @@ define([ } /** - * Converts a geometry's triangle indices to line indices. If the geometry has an indexList + * Converts a geometry's triangle indices to line indices. If the geometry has an indices * and its primitiveType is TRIANGLES, TRIANGLE_STRIP, * TRIANGLE_FAN, it is converted to LINES; otherwise, the geometry is not changed. *

    @@ -128,17 +128,17 @@ define([ throw new DeveloperError('geometry is required.'); } - var indices = geometry.indexList; + var indices = geometry.indices; if (typeof indices !== 'undefined') { switch (geometry.primitiveType) { case PrimitiveType.TRIANGLES: - geometry.indexList = trianglesToLines(indices); + geometry.indices = trianglesToLines(indices); break; case PrimitiveType.TRIANGLE_STRIP: - geometry.indexList = triangleStripToLines(indices); + geometry.indices = triangleStripToLines(indices); break; case PrimitiveType.TRIANGLE_FAN: - geometry.indexList = triangleFanToLines(indices); + geometry.indices = triangleFanToLines(indices); break; } @@ -189,7 +189,7 @@ define([ }; /** - * Reorders a geometry's attributes and indexList to achieve better performance from the GPU's pre-vertex-shader cache. + * Reorders a geometry's attributes and indices to achieve better performance from the GPU's pre-vertex-shader cache. * * @param {Geometry} geometry The geometry to modify, which is modified in place. * @@ -210,15 +210,15 @@ define([ var numVertices = Geometry.computeNumberOfVertices(geometry); - var indexList = geometry.indexList; - if (typeof indexList !== 'undefined') { + var indices = geometry.indices; + if (typeof indices !== 'undefined') { var indexCrossReferenceOldToNew = new Int32Array(numVertices); for ( var i = 0; i < numVertices; i++) { indexCrossReferenceOldToNew[i] = -1; } // Construct cross reference and reorder indices - var indicesIn = indexList; + var indicesIn = indices; var numIndices = indicesIn.length; var indicesOut = IndexDatatype.createTypedArray(numVertices, numIndices); @@ -243,7 +243,7 @@ define([ ++intoIndicesIn; ++intoIndicesOut; } - geometry.indexList = indicesOut; + geometry.indices = indicesOut; // Reorder attributes var attributes = geometry.attributes; @@ -270,9 +270,9 @@ define([ }; /** - * Reorders a geometry's indexList to achieve better performance from the GPU's + * Reorders a geometry's indices to achieve better performance from the GPU's * post vertex-shader cache by using the Tipsify algorithm. If the geometry primitiveType - * is not TRIANGLES or the geometry does not have an indexList, this function has no effect. + * is not TRIANGLES or the geometry does not have an indices, this function has no effect. * * @param {Geometry} geometry The geometry to modify, which is modified in place. * @param {Number} [cacheCapacity=24] The number of vertices that can be held in the GPU's vertex cache. @@ -295,7 +295,7 @@ define([ throw new DeveloperError('geometry is required.'); } - var indices = geometry.indexList; + var indices = geometry.indices; if ((geometry.primitiveType === PrimitiveType.TRIANGLES) && (typeof indices !== 'undefined')) { var numIndices = indices.length; var maximumIndex = 0; @@ -304,7 +304,7 @@ define([ maximumIndex = indices[j]; } } - geometry.indexList = Tipsify.tipsify({ + geometry.indices = Tipsify.tipsify({ indices : indices, maximumIndex : maximumIndex, cacheSize : cacheCapacity @@ -346,10 +346,10 @@ define([ /** * Splits a geometry into multiple geometries - if necessary - to ensure that indices in the - * indexList fit into unsigned shorts. This is used to meet the WebGL requirements + * indices fit into unsigned shorts. This is used to meet the WebGL requirements * when {@link Context#getElementIndexUint} is false. *

    - * If the geometry does not have an indexList, this function has no effect. + * If the geometry does not have an indices, this function has no effect. *

    * * @param {Geometry} geometry The geometry to modify, which is modified in place if it needs to be split into multiple geometries. @@ -368,7 +368,7 @@ define([ throw new DeveloperError('geometry is required.'); } - if ((typeof geometry.indexList !== 'undefined') && + if ((typeof geometry.indices !== 'undefined') && ((geometry.primitiveType !== PrimitiveType.TRIANGLES) && (geometry.primitiveType !== PrimitiveType.LINES) && (geometry.primitiveType !== PrimitiveType.POINTS))) { @@ -381,13 +381,13 @@ define([ // some indices are outside the range of unsigned short [0, 64K - 1] var numberOfVertices = Geometry.computeNumberOfVertices(geometry); var sixtyFourK = 64 * 1024; - if (typeof geometry.indexList !== 'undefined' && (numberOfVertices > sixtyFourK)) { + if (typeof geometry.indices !== 'undefined' && (numberOfVertices > sixtyFourK)) { var oldToNewIndex = []; var newIndices = []; var currentIndex = 0; var newAttributes = copyAttributesDescriptions(geometry.attributes); - var originalIndices = geometry.indexList; + var originalIndices = geometry.indices; var numberOfIndices = originalIndices.length; var indicesPerPrimitive; @@ -415,7 +415,7 @@ define([ if (currentIndex + indicesPerPrimitive > sixtyFourK) { geometries.push(new Geometry({ attributes : newAttributes, - indexList : newIndices, + indices : newIndices, primitiveType : geometry.primitiveType })); @@ -430,7 +430,7 @@ define([ if (newIndices.length !== 0) { geometries.push(new Geometry({ attributes : newAttributes, - indexList : newIndices, + indices : newIndices, primitiveType : geometry.primitiveType })); } @@ -720,7 +720,7 @@ define([ * * @exception {DeveloperError} instances is required and must have length greater than zero. * @exception {DeveloperError} All instances must have the same modelMatrix. - * @exception {DeveloperError} All instance geometries must have an indexList or not have one. + * @exception {DeveloperError} All instance geometries must have an indices or not have one. * @exception {DeveloperError} All instance geometries must have the same primitiveType. * * @example @@ -748,7 +748,7 @@ define([ var k; var m = instances[0].modelMatrix; - var haveIndexLists = (typeof instances[0].geometry.indexList !== 'undefined'); + var haveindicess = (typeof instances[0].geometry.indices !== 'undefined'); var primitiveType = instances[0].geometry.primitiveType; for (i = 1; i < length; ++i) { @@ -756,8 +756,8 @@ define([ throw new DeveloperError('All instances must have the same modelMatrix.'); } - if ((typeof instances[i].geometry.indexList !== 'undefined') !== haveIndexLists) { - throw new DeveloperError('All instance geometries must have an indexList or not have one.'); + if ((typeof instances[i].geometry.indices !== 'undefined') !== haveindicess) { + throw new DeveloperError('All instance geometries must have an indices or not have one.'); } if (instances[i].geometry.primitiveType !== primitiveType) { @@ -789,12 +789,12 @@ define([ } // Combine index lists - var indexList; + var indices; - if (haveIndexLists) { + if (haveindicess) { var numberOfIndices = 0; for (i = 0; i < length; ++i) { - numberOfIndices += instances[i].geometry.indexList.length; + numberOfIndices += instances[i].geometry.indices.length; } var numberOfVertices = Geometry.computeNumberOfVertices(new Geometry({ @@ -806,7 +806,7 @@ define([ var offset = 0; for (i = 0; i < length; ++i) { - var sourceIndices = instances[i].geometry.indexList; + var sourceIndices = instances[i].geometry.indices; var sourceIndicesLen = sourceIndices.length; for (k = 0; k < sourceIndicesLen; ++k) { @@ -816,7 +816,7 @@ define([ offset += Geometry.computeNumberOfVertices(instances[i].geometry); } - indexList = destIndices; + indices = destIndices; } // Create bounding sphere that includes all instances @@ -839,7 +839,7 @@ define([ return new Geometry({ attributes : attributes, - indexList : indexList, + indices : indices, primitiveType : primitiveType, boundingSphere : boundingSphere }); @@ -855,7 +855,7 @@ define([ * all triangles incident to the vertex. The result is a new normal attribute added to the geometry. * This assumes a counter-clockwise winding order. *

    - * This function has no effect if the geometry's indexList is undefined or the + * This function has no effect if the geometry's indices is undefined or the * primitiveType is not {@link PrimitiveType.TRIANGLES} or the geometry does not have a * position attribute. *

    @@ -875,7 +875,7 @@ define([ } var attributes = geometry.attributes; - var indices = geometry.indexList; + var indices = geometry.indices; if (typeof attributes.position === 'undefined' || typeof attributes.position.values === 'undefined' || @@ -996,7 +996,7 @@ define([ * The result is new binormal and tangent attributes added to the geometry. * This assumes a counter-clockwise winding order. *

    - * This function has no effect if the geometry's indexList is undefined or the + * This function has no effect if the geometry's indices is undefined or the * primitiveType is not {@link PrimitiveType.TRIANGLES} or the geometry does not have * position, normal, and st attributes. *

    @@ -1009,7 +1009,7 @@ define([ * @returns {Geometry} The modified geometry argument with the compute binormal and tangent attributes. * * @exception {DeveloperError} geometry is required. - * + *˙ * @example * geometry = GeometryPipeline.computeBinormalAndTangent(geometry); */ @@ -1022,7 +1022,7 @@ define([ var vertices = geometry.attributes.position.values; var normals = geometry.attributes.normal.values; var st = geometry.attributes.st.values; - var indices = geometry.indexList; + var indices = geometry.indices; if ((typeof attributes.position === 'undefined' || typeof attributes.position.values === 'undefined') || (typeof attributes.normal === 'undefined' || typeof attributes.normal.values === 'undefined') || diff --git a/Source/Core/IndexDatatype.js b/Source/Core/IndexDatatype.js index 47bd277ab113..0284605af24b 100644 --- a/Source/Core/IndexDatatype.js +++ b/Source/Core/IndexDatatype.js @@ -62,7 +62,7 @@ define([ * @exception {DeveloperError} center is required. * * @example - * this.indexList = IndexDatatype.createTypedArray(positions.length / 3, numberOfIndices); + * this.indices = IndexDatatype.createTypedArray(positions.length / 3, numberOfIndices); */ IndexDatatype.createTypedArray = function(numberOfVertices, indicesLengthOrArray) { if (typeof numberOfVertices === 'undefined') { diff --git a/Source/Core/PolygonGeometry.js b/Source/Core/PolygonGeometry.js index 63f8ef7062b4..9ef6e80f6843 100644 --- a/Source/Core/PolygonGeometry.js +++ b/Source/Core/PolygonGeometry.js @@ -423,7 +423,7 @@ define([ * * @type Array */ - this.indexList = geometry.indexList; + this.indices = geometry.indices; /** * The type of primitives in the geometry. For this geometry, it is {@link PrimitiveType.TRIANGLES}. diff --git a/Source/Core/PolygonPipeline.js b/Source/Core/PolygonPipeline.js index 2786de7dfbf1..21ada040d418 100644 --- a/Source/Core/PolygonPipeline.js +++ b/Source/Core/PolygonPipeline.js @@ -835,7 +835,7 @@ define([ values : flattenedPositions }) }, - indexList : subdividedIndices, + indices : subdividedIndices, primitiveType : PrimitiveType.TRIANGLES }); }, diff --git a/Source/Core/WallGeometry.js b/Source/Core/WallGeometry.js index fc5cef43a85e..f54ba0050238 100644 --- a/Source/Core/WallGeometry.js +++ b/Source/Core/WallGeometry.js @@ -289,7 +289,7 @@ define([ * * @type Array */ - this.indexList = indices; + this.indices = indices; /** * The type of primitives in the geometry. For this geometry, it is {@link PrimitiveType.TRIANGLES}. diff --git a/Source/Renderer/Context.js b/Source/Renderer/Context.js index 5022b5da30eb..a283b6768c55 100644 --- a/Source/Renderer/Context.js +++ b/Source/Renderer/Context.js @@ -2443,12 +2443,12 @@ define([ } var indexBuffer; - var indexList = geometry.indexList; - if (typeof indexList !== 'undefined') { + var indices = geometry.indices; + if (typeof indices !== 'undefined') { if ((Geometry.computeNumberOfVertices(geometry) > 64 * 1024) && this.getElementIndexUint()) { - indexBuffer = this.createIndexBuffer(new Uint32Array(indexList), bufferUsage, IndexDatatype.UNSIGNED_INT); + indexBuffer = this.createIndexBuffer(new Uint32Array(indices), bufferUsage, IndexDatatype.UNSIGNED_INT); } else{ - indexBuffer = this.createIndexBuffer(new Uint16Array(indexList), bufferUsage, IndexDatatype.UNSIGNED_SHORT); + indexBuffer = this.createIndexBuffer(new Uint16Array(indices), bufferUsage, IndexDatatype.UNSIGNED_SHORT); } } diff --git a/Source/Scene/CentralBody.js b/Source/Scene/CentralBody.js index f4f27e77aa3c..123593b4ea29 100644 --- a/Source/Scene/CentralBody.js +++ b/Source/Scene/CentralBody.js @@ -553,7 +553,7 @@ define([ values : depthQuad }) }, - indexList : [0, 1, 2, 2, 1, 3], + indices : [0, 1, 2, 2, 1, 3], primitiveType : PrimitiveType.TRIANGLES }); this._depthCommand.vertexArray = context.createVertexArrayFromGeometry({ diff --git a/Source/Scene/ImageryLayer.js b/Source/Scene/ImageryLayer.js index 5682974db40e..0337954c522a 100644 --- a/Source/Scene/ImageryLayer.js +++ b/Source/Scene/ImageryLayer.js @@ -807,7 +807,7 @@ define([ values : positions }) }, - indexList : TerrainProvider.getRegularGridIndices(256, 256), + indices : TerrainProvider.getRegularGridIndices(256, 256), primitiveType : PrimitiveType.TRIANGLES }); diff --git a/Specs/Core/BoxGeometrySpec.js b/Specs/Core/BoxGeometrySpec.js index b4fbe13263d5..962300714853 100644 --- a/Specs/Core/BoxGeometrySpec.js +++ b/Specs/Core/BoxGeometrySpec.js @@ -27,7 +27,7 @@ defineSuite([ }); expect(m.attributes.position.values.length).toEqual(8 * 3); - expect(m.indexList.length).toEqual(12 * 3); + expect(m.indices.length).toEqual(12 * 3); }); it('constructor computes all vertex attributes', function() { @@ -45,7 +45,7 @@ defineSuite([ expect(m.attributes.binormal.values.length).toEqual(6 * 4 * 3); expect(m.attributes.st.values.length).toEqual(6 * 4 * 2); - expect(m.indexList.length).toEqual(12 * 3); + expect(m.indices.length).toEqual(12 * 3); expect(m.boundingSphere.center).toEqual(Cartesian3.ZERO); expect(m.boundingSphere.radius).toEqual(maximumCorner.magnitude() * 0.5); diff --git a/Specs/Core/CircleGeometrySpec.js b/Specs/Core/CircleGeometrySpec.js index fccea149d7d2..bf9c9166b7ba 100644 --- a/Specs/Core/CircleGeometrySpec.js +++ b/Specs/Core/CircleGeometrySpec.js @@ -60,7 +60,7 @@ defineSuite([ }); expect(m.attributes.position.values.length).toEqual(3 * 24); - expect(m.indexList.length).toEqual(3 * 34); + expect(m.indices.length).toEqual(3 * 34); expect(m.boundingSphere.radius).toEqual(1); }); @@ -79,6 +79,6 @@ defineSuite([ expect(m.attributes.normal.values.length).toEqual(3 * 24); expect(m.attributes.tangent.values.length).toEqual(3 * 24); expect(m.attributes.binormal.values.length).toEqual(3 * 24); - expect(m.indexList.length).toEqual(3 * 34); + expect(m.indices.length).toEqual(3 * 34); }); }); diff --git a/Specs/Core/EllipseGeometrySpec.js b/Specs/Core/EllipseGeometrySpec.js index 4f6876b8418e..596c3ab78749 100644 --- a/Specs/Core/EllipseGeometrySpec.js +++ b/Specs/Core/EllipseGeometrySpec.js @@ -74,7 +74,7 @@ defineSuite([ }); expect(m.attributes.position.values.length).toEqual(3 * 24); - expect(m.indexList.length).toEqual(3 * 34); + expect(m.indices.length).toEqual(3 * 34); expect(m.boundingSphere.radius).toEqual(1); }); @@ -94,6 +94,6 @@ defineSuite([ expect(m.attributes.normal.values.length).toEqual(3 * 24); expect(m.attributes.tangent.values.length).toEqual(3 * 24); expect(m.attributes.binormal.values.length).toEqual(3 * 24); - expect(m.indexList.length).toEqual(3 * 34); + expect(m.indices.length).toEqual(3 * 34); }); }); diff --git a/Specs/Core/EllipsoidGeometrySpec.js b/Specs/Core/EllipsoidGeometrySpec.js index 05972bb2250f..f4332794cb5d 100644 --- a/Specs/Core/EllipsoidGeometrySpec.js +++ b/Specs/Core/EllipsoidGeometrySpec.js @@ -30,7 +30,7 @@ defineSuite([ }); expect(m.attributes.position.values.length).toEqual(3 * 8); - expect(m.indexList.length).toEqual(12 * 3); + expect(m.indices.length).toEqual(12 * 3); expect(m.boundingSphere.radius).toEqual(1); }); @@ -46,7 +46,7 @@ defineSuite([ expect(m.attributes.normal.values.length).toEqual(3 * (8 + 6 + 12)); expect(m.attributes.tangent.values.length).toEqual(3 * (8 + 6 + 12)); expect(m.attributes.binormal.values.length).toEqual(3 * (8 + 6 + 12)); - expect(m.indexList.length).toEqual(2 * 3 * 4 * 6); + expect(m.indices.length).toEqual(2 * 3 * 4 * 6); }); it('computes attributes for a unit sphere', function() { diff --git a/Specs/Core/ExtentGeometrySpec.js b/Specs/Core/ExtentGeometrySpec.js index 661b9f85de66..86a0abc83495 100644 --- a/Specs/Core/ExtentGeometrySpec.js +++ b/Specs/Core/ExtentGeometrySpec.js @@ -31,7 +31,7 @@ defineSuite([ var length = positions.length; expect(positions.length).toEqual(9 * 3); - expect(m.indexList.length).toEqual(8 * 3); + expect(m.indices.length).toEqual(8 * 3); var expectedNWCorner = Ellipsoid.WGS84.cartographicToCartesian(extent.getNorthwest()); var expectedSECorner = Ellipsoid.WGS84.cartographicToCartesian(extent.getSoutheast()); @@ -50,7 +50,7 @@ defineSuite([ expect(m.attributes.normal.values.length).toEqual(9 * 3); expect(m.attributes.tangent.values.length).toEqual(9 * 3); expect(m.attributes.binormal.values.length).toEqual(9 * 3); - expect(m.indexList.length).toEqual(8 * 3); + expect(m.indices.length).toEqual(8 * 3); }); it('compute positions with rotation', function() { @@ -66,7 +66,7 @@ defineSuite([ var length = positions.length; expect(length).toEqual(9 * 3); - expect(m.indexList.length).toEqual(8 * 3); + expect(m.indices.length).toEqual(8 * 3); var unrotatedSECorner = extent.getSoutheast(); var projection = new GeographicProjection(); @@ -89,7 +89,7 @@ defineSuite([ var length = positions.length; expect(length).toEqual(9 * 3); - expect(m.indexList.length).toEqual(8 * 3); + expect(m.indices.length).toEqual(8 * 3); var unrotatedNWCorner = Ellipsoid.WGS84.cartographicToCartesian(extent.getNorthwest()); var unrotatedSECorner = Ellipsoid.WGS84.cartographicToCartesian(extent.getSoutheast()); diff --git a/Specs/Core/GeometryPipelineSpec.js b/Specs/Core/GeometryPipelineSpec.js index 45062d89b312..fd27e9820f55 100644 --- a/Specs/Core/GeometryPipelineSpec.js +++ b/Specs/Core/GeometryPipelineSpec.js @@ -36,13 +36,13 @@ defineSuite([ it('converts triangles to wireframe in place', function() { var geometry = GeometryPipeline.toWireframe(new Geometry({ - indexList : [0, 1, 2, 3, 4, 5], + indices : [0, 1, 2, 3, 4, 5], primitiveType : PrimitiveType.TRIANGLES })); expect(geometry.primitiveType).toEqual(PrimitiveType.LINES); - var v = geometry.indexList; + var v = geometry.indices; expect(v.length).toEqual(12); expect(v[0]).toEqual(0); @@ -62,13 +62,13 @@ defineSuite([ it('converts a triangle fan to wireframe in place', function() { var geometry = GeometryPipeline.toWireframe(new Geometry({ - indexList : [0, 1, 2, 3], + indices : [0, 1, 2, 3], primitiveType : PrimitiveType.TRIANGLE_FAN })); expect(geometry.primitiveType).toEqual(PrimitiveType.LINES); - var v = geometry.indexList; + var v = geometry.indices; expect(v.length).toEqual(12); expect(v[0]).toEqual(0); @@ -88,13 +88,13 @@ defineSuite([ it('converts a triangle strip to wireframe in place', function() { var geometry = GeometryPipeline.toWireframe(new Geometry({ - indexList : [0, 1, 2, 3], + indices : [0, 1, 2, 3], primitiveType : PrimitiveType.TRIANGLE_STRIP })); expect(geometry.primitiveType).toEqual(PrimitiveType.LINES); - var v = geometry.indexList; + var v = geometry.indices; expect(v.length).toEqual(12); expect(v[0]).toEqual(0); @@ -157,24 +157,24 @@ defineSuite([ values : [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0] }) }, - indexList : [5, 3, 2, 0, 1, 4, 4, 1, 3, 2, 5, 0], + indices : [5, 3, 2, 0, 1, 4, 4, 1, 3, 2, 5, 0], primitiveType : PrimitiveType.TRIANGLES }); GeometryPipeline.reorderForPreVertexCache(geometry); - expect(geometry.indexList[0]).toEqual(0); - expect(geometry.indexList[1]).toEqual(1); - expect(geometry.indexList[2]).toEqual(2); - expect(geometry.indexList[3]).toEqual(3); - expect(geometry.indexList[4]).toEqual(4); - expect(geometry.indexList[5]).toEqual(5); - expect(geometry.indexList[6]).toEqual(5); - expect(geometry.indexList[7]).toEqual(4); - expect(geometry.indexList[8]).toEqual(1); - expect(geometry.indexList[9]).toEqual(2); - expect(geometry.indexList[10]).toEqual(0); - expect(geometry.indexList[11]).toEqual(3); + expect(geometry.indices[0]).toEqual(0); + expect(geometry.indices[1]).toEqual(1); + expect(geometry.indices[2]).toEqual(2); + expect(geometry.indices[3]).toEqual(3); + expect(geometry.indices[4]).toEqual(4); + expect(geometry.indices[5]).toEqual(5); + expect(geometry.indices[6]).toEqual(5); + expect(geometry.indices[7]).toEqual(4); + expect(geometry.indices[8]).toEqual(1); + expect(geometry.indices[9]).toEqual(2); + expect(geometry.indices[10]).toEqual(0); + expect(geometry.indices[11]).toEqual(3); expect(geometry.attributes.weight.values[0]).toEqual(5.0); expect(geometry.attributes.weight.values[1]).toEqual(3.0); @@ -233,13 +233,13 @@ defineSuite([ it('reorderForPostVertexCache reorders indices for the post vertex cache', function() { var geometry = new EllipsoidGeometry(); var acmrBefore = Tipsify.calculateACMR({ - indices : geometry.indexList, + indices : geometry.indices, cacheSize : 24 }); expect(acmrBefore).toBeGreaterThan(1.0); geometry = GeometryPipeline.reorderForPostVertexCache(geometry); var acmrAfter = Tipsify.calculateACMR({ - indices : geometry.indexList, + indices : geometry.indices, cacheSize : 24 }); expect(acmrAfter).toBeLessThan(0.7); @@ -265,7 +265,7 @@ defineSuite([ values : [1.0] }) }, - indexList : [0, 0, 0], + indices : [0, 0, 0], primitiveType : PrimitiveType.TRIANGLES }); @@ -290,7 +290,7 @@ defineSuite([ values : times }) }, - indexList : [0, 0, 0, sixtyFourK, sixtyFourK, sixtyFourK, 0, sixtyFourK, 0], + indices : [0, 0, 0, sixtyFourK, sixtyFourK, sixtyFourK, 0, sixtyFourK, 0], primitiveType : PrimitiveType.TRIANGLES }); @@ -302,7 +302,7 @@ defineSuite([ expect(geometries[0].attributes.time.values).toEqual([0, sixtyFourK]); expect(geometries[0].primitiveType).toEqual(PrimitiveType.TRIANGLES); - expect(geometries[0].indexList).toEqual([0, 0, 0, 1, 1, 1, 0, 1, 0]); + expect(geometries[0].indices).toEqual([0, 0, 0, 1, 1, 1, 0, 1, 0]); }); it('fitToUnsignedShortIndices creates two triangle geometries', function() { @@ -327,7 +327,7 @@ defineSuite([ values : positions }) }, - indexList : indices, + indices : indices, primitiveType : PrimitiveType.TRIANGLES }); @@ -336,10 +336,10 @@ defineSuite([ expect(geometries.length).toEqual(2); expect(geometries[0].attributes.position.values.length).toEqual(positions.length - 6); // Two vertices are not copied (0, 1) - expect(geometries[0].indexList.length).toEqual(indices.length - 3); // One triangle is not copied (0, 1, 2) + expect(geometries[0].indices.length).toEqual(indices.length - 3); // One triangle is not copied (0, 1, 2) expect(geometries[1].attributes.position.values.length).toEqual(9); - expect(geometries[1].indexList.length).toEqual(3); + expect(geometries[1].indices.length).toEqual(3); }); it('fitToUnsignedShortIndices creates two line geometries', function() { @@ -364,7 +364,7 @@ defineSuite([ values : positions }) }, - indexList : indices, + indices : indices, primitiveType : PrimitiveType.LINES }); @@ -373,10 +373,10 @@ defineSuite([ expect(geometries.length).toEqual(2); expect(geometries[0].attributes.position.values.length).toEqual(positions.length - 6); // Two vertices are not copied (0, 1) - expect(geometries[0].indexList.length).toEqual(indices.length - 2); // One line is not copied (0, 1) + expect(geometries[0].indices.length).toEqual(indices.length - 2); // One line is not copied (0, 1) expect(geometries[1].attributes.position.values.length).toEqual(6); - expect(geometries[1].indexList.length).toEqual(2); + expect(geometries[1].indices.length).toEqual(2); }); it('fitToUnsignedShortIndices creates two point geometries', function() { @@ -397,7 +397,7 @@ defineSuite([ values : positions }) }, - indexList : indices, + indices : indices, primitiveType : PrimitiveType.POINTS }); @@ -406,10 +406,10 @@ defineSuite([ expect(geometries.length).toEqual(2); expect(geometries[0].attributes.position.values.length).toEqual(positions.length - 3); // One vertex is not copied - expect(geometries[0].indexList.length).toEqual(indices.length - 1); // One point is not copied + expect(geometries[0].indices.length).toEqual(indices.length - 1); // One point is not copied expect(geometries[1].attributes.position.values.length).toEqual(3); - expect(geometries[1].indexList.length).toEqual(1); + expect(geometries[1].indices.length).toEqual(1); }); it('fitToUnsignedShortIndices throws without a geometry', function() { @@ -427,7 +427,7 @@ defineSuite([ values : [10.0, 11.0, 12.0] }) }, - indexList : [0, 1, 2], + indices : [0, 1, 2], primitiveType : PrimitiveType.TRIANGLE_STRIP }); @@ -450,7 +450,7 @@ defineSuite([ values : [1.0, 2.0] }) }, - indexList : [0, 0, 0], + indices : [0, 0, 0], primitiveType : PrimitiveType.TRIANGLES }); @@ -571,7 +571,7 @@ defineSuite([ expect(combined).toBe(instance.geometry); }); - it('combine combines several geometries without indexLists', function() { + it('combine combines several geometries without indicess', function() { var instance = new GeometryInstance({ geometry : new Geometry({ attributes : { @@ -610,7 +610,7 @@ defineSuite([ })); }); - it('combine combines several geometries with indexLists', function() { + it('combine combines several geometries with indicess', function() { var instance = new GeometryInstance({ geometry : new Geometry({ attributes : { @@ -633,7 +633,7 @@ defineSuite([ ] }) }, - indexList : [0, 1, 2], + indices : [0, 1, 2], primitiveType : PrimitiveType.TRIANGLES }) }); @@ -650,7 +650,7 @@ defineSuite([ ] }) }, - indexList : [0, 1, 2], + indices : [0, 1, 2], primitiveType : PrimitiveType.TRIANGLES }) }); @@ -671,7 +671,7 @@ defineSuite([ ]) }) }, - indexList : new Uint16Array([0, 1, 2, 3, 4, 5]), + indices : new Uint16Array([0, 1, 2, 3, 4, 5]), primitiveType : PrimitiveType.TRIANGLES })); }); @@ -720,7 +720,7 @@ defineSuite([ }).toThrow(); }); - it('combine throws when instance geometries do not all have or not have an indexList', function() { + it('combine throws when instance geometries do not all have or not have an indices', function() { var instance0 = new GeometryInstance({ geometry : new Geometry({ attributes : new GeometryAttribute({ @@ -730,7 +730,7 @@ defineSuite([ values : [0.0, 0.0, 0.0] } }), - indexList : [0] + indices : [0] }) }); @@ -757,7 +757,7 @@ defineSuite([ }).toThrow(); }); - it('computeNormal does not compute normals when geometry.indexList is undefined', function() { + it('computeNormal does not compute normals when geometry.indices is undefined', function() { var geometry = new Geometry({ attributes: { position: new GeometryAttribute({ @@ -780,7 +780,7 @@ defineSuite([ componentsPerAttribute: 3 }) }, - indexList : [0, 1, 2], + indices : [0, 1, 2], primitiveType: PrimitiveType.TRIANGLE_STRIP }); @@ -798,7 +798,7 @@ defineSuite([ componentsPerAttribute: 3 }) }, - indexList : [0, 1, 2], + indices : [0, 1, 2], primitiveType: PrimitiveType.TRIANGLES }); @@ -816,7 +816,7 @@ defineSuite([ componentsPerAttribute: 3 }) }, - indexList : [0, 1, 2, 1, 3, 2], + indices : [0, 1, 2, 1, 3, 2], primitiveType: PrimitiveType.TRIANGLES }); @@ -843,7 +843,7 @@ defineSuite([ componentsPerAttribute: 3 }) }, - indexList : [0, 1, 2, 3, 0, 2, 4, 0, 3, 4, 5, 0, 5, 6, 0, 6, 1, 0], + indices : [0, 1, 2, 3, 0, 2, 4, 0, 3, 4, 5, 0, 5, 6, 0, 6, 1, 0], primitiveType: PrimitiveType.TRIANGLES }); @@ -877,7 +877,7 @@ defineSuite([ }).toThrow(); }); - it('computeBinormalAndTangent does not compute tangent and binormals when geometry.indexList is undefined', function() { + it('computeBinormalAndTangent does not compute tangent and binormals when geometry.indices is undefined', function() { var geometry = new Geometry({ attributes: { position: new GeometryAttribute({ @@ -920,7 +920,7 @@ defineSuite([ componentsPerAttribute: 2 }) }, - indexList : [0, 1, 2], + indices : [0, 1, 2], primitiveType: PrimitiveType.TRIANGLE_STRIP }); @@ -942,7 +942,7 @@ defineSuite([ componentsPerAttribute: 2 }) }, - indexList : [0, 1, 2], + indices : [0, 1, 2], primitiveType: PrimitiveType.TRIANGLES }); @@ -965,7 +965,7 @@ defineSuite([ componentsPerAttribute: 2 }) }, - indexList : [0, 1, 2, 1, 3, 2], + indices : [0, 1, 2, 1, 3, 2], primitiveType: PrimitiveType.TRIANGLES }); diff --git a/Specs/Core/PolygonGeometrySpec.js b/Specs/Core/PolygonGeometrySpec.js index 1d0c5bc6a02f..96468a521468 100644 --- a/Specs/Core/PolygonGeometrySpec.js +++ b/Specs/Core/PolygonGeometrySpec.js @@ -93,7 +93,7 @@ defineSuite([ }); expect(p.attributes.position.values.length).toEqual(3 * 11); - expect(p.indexList.length).toEqual(3 * 14); + expect(p.indices.length).toEqual(3 * 14); }); it('computes all attributes', function() { @@ -113,7 +113,7 @@ defineSuite([ expect(p.attributes.normal.values.length).toEqual(3 * 11); expect(p.attributes.tangent.values.length).toEqual(3 * 11); expect(p.attributes.binormal.values.length).toEqual(3 * 11); - expect(p.indexList.length).toEqual(3 * 14); + expect(p.indices.length).toEqual(3 * 14); }); it('creates a polygon from hierarchy', function() { @@ -149,7 +149,7 @@ defineSuite([ }); expect(p.attributes.position.values.length).toEqual(3 * 14); - expect(p.indexList.length).toEqual(3 * 10); + expect(p.indices.length).toEqual(3 * 10); }); it('creates a polygon from clockwise hierarchy', function() { @@ -185,7 +185,7 @@ defineSuite([ }); expect(p.attributes.position.values.length).toEqual(3 * 14); - expect(p.indexList.length).toEqual(3 * 10); + expect(p.indices.length).toEqual(3 * 10); }); }, 'WebGL'); diff --git a/Specs/Core/PolygonPipelineSpec.js b/Specs/Core/PolygonPipelineSpec.js index bf967b6e0cd4..6f93aeff22b4 100644 --- a/Specs/Core/PolygonPipelineSpec.js +++ b/Specs/Core/PolygonPipelineSpec.js @@ -360,9 +360,9 @@ defineSuite([ expect(subdivision.attributes.position.values[7]).toEqual(0.0); expect(subdivision.attributes.position.values[8]).toEqual(0.0); - expect(subdivision.indexList[0]).toEqual(0); - expect(subdivision.indexList[1]).toEqual(1); - expect(subdivision.indexList[2]).toEqual(2); + expect(subdivision.indices[0]).toEqual(0); + expect(subdivision.indices[1]).toEqual(1); + expect(subdivision.indices[2]).toEqual(2); }); it('eliminateHoles throws an exception without an outerRing', function() { diff --git a/Specs/Core/WallGeometrySpec.js b/Specs/Core/WallGeometrySpec.js index 1f45c2b8064f..76f714737d6a 100644 --- a/Specs/Core/WallGeometrySpec.js +++ b/Specs/Core/WallGeometrySpec.js @@ -42,7 +42,7 @@ defineSuite([ }); expect(w.attributes.position.values.length).toEqual(2 * 2 * 3); - expect(w.indexList.length).toEqual(2 * 3); + expect(w.indices.length).toEqual(2 * 3); }); it('creates positions relative to terrain', function() { @@ -63,7 +63,7 @@ defineSuite([ }); expect(w.attributes.position.values.length).toEqual(2 * 2 * 3); - expect(w.indexList.length).toEqual(2 * 3); + expect(w.indices.length).toEqual(2 * 3); }); it('creates all attributes', function() { @@ -83,7 +83,7 @@ defineSuite([ expect(w.attributes.tangent.values.length).toEqual(3 * 2 * 3); expect(w.attributes.binormal.values.length).toEqual(3 * 2 * 3); expect(w.attributes.st.values.length).toEqual(3 * 2 * 2); - expect(w.indexList.length).toEqual((3 * 2 - 2) * 3); + expect(w.indices.length).toEqual((3 * 2 - 2) * 3); }); }); diff --git a/Specs/Renderer/VertexArrayFactorySpec.js b/Specs/Renderer/VertexArrayFactorySpec.js index 4fe2ba121318..6d7b1c2149e7 100644 --- a/Specs/Renderer/VertexArrayFactorySpec.js +++ b/Specs/Renderer/VertexArrayFactorySpec.js @@ -544,7 +544,7 @@ defineSuite([ it('creates an index buffer', function() { var geometry = new Geometry({ - indexList : [0], + indices : [0], primitiveType : PrimitiveType.POINTS }); @@ -556,7 +556,7 @@ defineSuite([ expect(va.getIndexBuffer()).toBeDefined(); expect(va.getIndexBuffer().getUsage()).toEqual(BufferUsage.DYNAMIC_DRAW); // Default expect(va.getIndexBuffer().getIndexDatatype()).toEqual(IndexDatatype.UNSIGNED_SHORT); - expect(va.getIndexBuffer().getNumberOfIndices()).toEqual(geometry.indexList.length); + expect(va.getIndexBuffer().getNumberOfIndices()).toEqual(geometry.indices.length); }); it('throws with different number of interleaved attributes', function() { From 313e93909a3f4303af832d67d8f4b76aaa9e4219 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Fri, 14 Jun 2013 11:57:08 -0400 Subject: [PATCH 182/306] More doc --- Source/Core/BoxGeometry.js | 2 +- Source/Core/CircleGeometry.js | 2 +- Source/Core/EllipseGeometry.js | 2 +- Source/Core/EllipsoidGeometry.js | 2 +- Source/Core/ExtentGeometry.js | 2 +- Source/Core/Geometry.js | 18 +++++++++--------- Source/Core/GeometryAttribute.js | 21 ++++++++++++++++++--- Source/Core/GeometryInstance.js | 17 ++++++++++++++--- Source/Core/GeometryPipeline.js | 15 ++++++++++++++- Source/Core/PolygonGeometry.js | 2 +- Source/Core/VertexFormat.js | 2 +- Source/Core/WallGeometry.js | 2 +- Source/Scene/Primitive.js | 2 +- 13 files changed, 64 insertions(+), 25 deletions(-) diff --git a/Source/Core/BoxGeometry.js b/Source/Core/BoxGeometry.js index 5d39a1b8deda..6b0216c05b83 100644 --- a/Source/Core/BoxGeometry.js +++ b/Source/Core/BoxGeometry.js @@ -377,7 +377,7 @@ define([ * * @type Object * - * @see Geometry.attributes + * @see Geometry#attributes */ this.attributes = attributes; diff --git a/Source/Core/CircleGeometry.js b/Source/Core/CircleGeometry.js index aa906ec6ae5d..1137f8fe42cd 100644 --- a/Source/Core/CircleGeometry.js +++ b/Source/Core/CircleGeometry.js @@ -61,7 +61,7 @@ define([ * * @type Object * - * @see Geometry.attributes + * @see Geometry#attributes */ this.attributes = ellipseGeometry.attributes; diff --git a/Source/Core/EllipseGeometry.js b/Source/Core/EllipseGeometry.js index a528d96ea14d..345a8dcc17f0 100644 --- a/Source/Core/EllipseGeometry.js +++ b/Source/Core/EllipseGeometry.js @@ -429,7 +429,7 @@ define([ * * @type Object * - * @see Geometry.attributes + * @see Geometry#attributes */ this.attributes = attributes; diff --git a/Source/Core/EllipsoidGeometry.js b/Source/Core/EllipsoidGeometry.js index 21ca3146ca10..c1e832a1ba5a 100644 --- a/Source/Core/EllipsoidGeometry.js +++ b/Source/Core/EllipsoidGeometry.js @@ -311,7 +311,7 @@ define([ * * @type Object * - * @see Geometry.attributes + * @see Geometry#attributes */ this.attributes = attributes; diff --git a/Source/Core/ExtentGeometry.js b/Source/Core/ExtentGeometry.js index 7c9b84b70ef5..edaa0ac566cf 100644 --- a/Source/Core/ExtentGeometry.js +++ b/Source/Core/ExtentGeometry.js @@ -301,7 +301,7 @@ define([ * * @type Object * - * @see Geometry.attributes + * @see Geometry#attributes */ this.attributes = attributes; diff --git a/Source/Core/Geometry.js b/Source/Core/Geometry.js index 5c0f0276d276..e39f0a1361d8 100644 --- a/Source/Core/Geometry.js +++ b/Source/Core/Geometry.js @@ -67,11 +67,11 @@ define([ * There are reserved attribute names with well-known semantics. The following attributes * are created by a Geometry (depending on the provided {@link VertexFormat}. *
      - *
    • position - 3D vertex position. 64-bit floating-point (for precision). 3 components per attribute. See {@link VertexFormat.position}.
    • - *
    • normal - Normal (normalized), commonly used for lighting. 32-bit floating-point. 3 components per attribute. See {@link VertexFormat.normal}.
    • - *
    • st - 2D texture coordinate. 32-bit floating-point. 2 components per attribute. See {@link VertexFormat.st}.
    • - *
    • binormal - Binormal (normalized), used for tangent-space effects like bump mapping. 32-bit floating-point. 3 components per attribute. See {@link VertexFormat.binormal}.
    • - *
    • tangent - Tangent (normalized), used for tangent-space effects like bump mapping. 32-bit floating-point. 3 components per attribute. See {@link VertexFormat.tangent}.
    • + *
    • position - 3D vertex position. 64-bit floating-point (for precision). 3 components per attribute. See {@link VertexFormat#position}.
    • + *
    • normal - Normal (normalized), commonly used for lighting. 32-bit floating-point. 3 components per attribute. See {@link VertexFormat#normal}.
    • + *
    • st - 2D texture coordinate. 32-bit floating-point. 2 components per attribute. See {@link VertexFormat#st}.
    • + *
    • binormal - Binormal (normalized), used for tangent-space effects like bump mapping. 32-bit floating-point. 3 components per attribute. See {@link VertexFormat#binormal}.
    • + *
    • tangent - Tangent (normalized), used for tangent-space effects like bump mapping. 32-bit floating-point. 3 components per attribute. See {@link VertexFormat#tangent}.
    • *
    *

    *

    @@ -83,7 +83,7 @@ define([ *

  • position3DLow - Low 32 bits for encoded 64-bit position computed with {@link GeometryPipeline.encodeAttribute}. 32-bit floating-point. 4 components per attribute.
  • *
  • position3DHigh - High 32 bits for encoded 64-bit 2D (Columbus view) position computed with {@link GeometryPipeline.encodeAttribute}. 32-bit floating-point. 4 components per attribute.
  • *
  • position2DLow - Low 32 bits for encoded 64-bit 2D (Columbus view) position computed with {@link GeometryPipeline.encodeAttribute}. 32-bit floating-point. 4 components per attribute.
  • - *
  • color - RGBA color (normalized) usually from {@link GeometryInstance.color}. 32-bit floating-point. 4 components per attribute.
  • + *
  • color - RGBA color (normalized) usually from {@link GeometryInstance#color}. 32-bit floating-point. 4 components per attribute.
  • *
  • pickColor - RGBA color used for picking, created from {@link Context#createPickId}. 32-bit floating-point. 4 components per attribute.
  • *
*

@@ -153,10 +153,10 @@ define([ * * @memberof Geometry * - * @param {Cartesian3} geometry The geometry to duplicate. If this is undefined, undefined is returned. - * @param {Cartesian3} [result] The object onto which to store the result. + * @param {Geometry} geometry The geometry to duplicate. If this is undefined, undefined is returned. + * @param {Geometry} [result] The object onto which to store the result. * - * @return {Cartesian3} The modified result parameter or a new Geometry instance if one was not provided. + * @return {Geometry} The modified result parameter or a new Geometry instance if one was not provided. * * @example * result.geometry = Geometry.clone(this.geometry); diff --git a/Source/Core/GeometryAttribute.js b/Source/Core/GeometryAttribute.js index fe73bba76156..10908318dcf5 100644 --- a/Source/Core/GeometryAttribute.js +++ b/Source/Core/GeometryAttribute.js @@ -6,11 +6,18 @@ define([ "use strict"; /** - * DOC_TBA + * Values and type information for geometry attributes. A {@link Geometry} + * generally contains one or more attributes. All attributes together form + * the geometry's vertices. * * @alias GeometryAttribute * @constructor * + * @param {ComponentDatatype} [options.componentDatatype=undefined] The datatype of each component in the attribute, e.g., individual elements in values. + * @param {Number} [options.componentsPerAttribute=undefined] A number between 1 and 4 that defines the number of components in an attributes. + * @param {Boolean} [options.normalize=false] When true and componentDatatype is an integer format, indicate that the components should be mapped to the range [0, 1] (unsigned) or [-1, 1] (signed) when they are accessed as floating-point for rendering. + * @param {Array} [options.values=undefined] The values for the attributes stored in a typed array. + * * @example * var geometry = new Geometry({ * attributes : { @@ -26,6 +33,8 @@ define([ * }, * primitiveType : PrimitiveType.LINE_LOOP * }); + * + * @see Geometry */ var GeometryAttribute = function(options) { options = defaultValue(options, defaultValue.EMPTY_OBJECT); @@ -107,14 +116,20 @@ define([ }; /** - * DOC_TBA + * Duplicates a GeometryAttribute instance, including a deep copy of {@link GeometryAttribute#values}. + * + * @memberof Geometry + * + * @param {GeometryAttribute} [result] The object onto which to store the result. + * + * @return {GeometryAttribute} The modified result parameter or a new GeometryAttribute instance if one was not provided. */ GeometryAttribute.prototype.clone = function(result) { if (typeof result === 'undefined') { result = new GeometryAttribute(); } - result.componentDatatype = this.componentDatatype; // Shallow copy enum + result.componentDatatype = this.componentDatatype; result.componentsPerAttribute = this.componentsPerAttribute; result.normalize = this.normalize; result.values = new this.values.constructor(this.values); diff --git a/Source/Core/GeometryInstance.js b/Source/Core/GeometryInstance.js index d6681ee91afe..baaae0ad8195 100644 --- a/Source/Core/GeometryInstance.js +++ b/Source/Core/GeometryInstance.js @@ -21,7 +21,7 @@ define([ * @param {Geometry} [options.geometry=undefined] The geometry to instance. * @param {Matrix4} [options.modelMatrix=Matrix4.IDENTITY] The model matrix that transforms to transform the geometry from model to world coordinates. * @param {Color} [options.color=undefined] The color of the instance when a per-instance color appearance is used. - * @param {Object} [options.pickData=undefined] A user-defined object to return when the instance is picked with {@link Context.pick} + * @param {Object} [options.pickData=undefined] A user-defined object to return when the instance is picked with {@link Context#pick} * * @example * // Create geometry for a box, and two instances that refer to it. @@ -86,13 +86,24 @@ define([ * * @default undefined * - * @see Context.pick + * @see Context#pick */ this.pickData = options.pickData; }; /** - * DOC_TBA + * Duplicates a GeometryInstance instance, including a deep copy of the geometry. + *

+ * {@link GeometryInstance#pickData} is shallow copied so that the same + * pickData reference is returned by {@link Context#pick} regardless of + * if the geometry instance was cloned. + *

+ * + * @memberof GeometryInstance + * + * @param {Geometry} [result] The object onto which to store the result. + * + * @return {Geometry} The modified result parameter or a new GeometryInstance instance if one was not provided. */ GeometryInstance.prototype.clone = function(result) { if (typeof result === 'undefined') { diff --git a/Source/Core/GeometryPipeline.js b/Source/Core/GeometryPipeline.js index 0069411cdca9..1b59fe6b0eba 100644 --- a/Source/Core/GeometryPipeline.js +++ b/Source/Core/GeometryPipeline.js @@ -716,7 +716,20 @@ define([ } /** - * DOC_TBA + * Combines geometry from several {@link GeometryInstance} objects into one geometry. + * This concatenates the attributes, concatenates and adjusts the indices, and creates + * a bounding sphere encompassing all instances. + *

+ * If the instances do not have the same attributes, a subset of attributes common + * to all instances is used, and the others are ignored. + *

+ *

+ * This is used by {@link Primitive} to efficiently render a large amount of static data. + *

+ * + * @param {Array} [instances] The array of {@link GeometryInstance} objects whose geometry will be combined. + * + * @returns {Geometry} A new geometry created from the provided geometry instances. * * @exception {DeveloperError} instances is required and must have length greater than zero. * @exception {DeveloperError} All instances must have the same modelMatrix. diff --git a/Source/Core/PolygonGeometry.js b/Source/Core/PolygonGeometry.js index 9ef6e80f6843..198e79fead7a 100644 --- a/Source/Core/PolygonGeometry.js +++ b/Source/Core/PolygonGeometry.js @@ -414,7 +414,7 @@ define([ * * @type Object * - * @see Geometry.attributes + * @see Geometry#attributes */ this.attributes = attributes; diff --git a/Source/Core/VertexFormat.js b/Source/Core/VertexFormat.js index 04cbc3d73dd8..f2b64becdeac 100644 --- a/Source/Core/VertexFormat.js +++ b/Source/Core/VertexFormat.js @@ -24,7 +24,7 @@ define([ * st : true * }); * - * @see Geometry.attributes + * @see Geometry#attributes */ var VertexFormat = function(options) { options = defaultValue(options, defaultValue.EMPTY_OBJECT); diff --git a/Source/Core/WallGeometry.js b/Source/Core/WallGeometry.js index f54ba0050238..235174881047 100644 --- a/Source/Core/WallGeometry.js +++ b/Source/Core/WallGeometry.js @@ -280,7 +280,7 @@ define([ * * @type Object * - * @see Geometry.attributes + * @see Geometry#attributes */ this.attributes = attributes; diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index eb3f3bb944b1..ff843f877a26 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -49,7 +49,7 @@ define([ *

*

* Combing multiple instances in one primitive is called batching, and significantly improves performance for static data. - * Instances can be individually picked; {@link Context.pick} returns their {@link GeometryInstance#pickData}. Using + * Instances can be individually picked; {@link Context#pick} returns their {@link GeometryInstance#pickData}. Using * per-instance appearances like {@link PerInstanceColorClosedTranslucentAppearance}, each instance can also have a unique color. *

* From 20322b473214961e080c11bd424a7a23973d4273 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Mon, 17 Jun 2013 14:00:04 -0400 Subject: [PATCH 183/306] More doc --- Source/Core/ComponentDatatype.js | 51 +++++++++++++++++++++++--------- Source/Core/IndexDatatype.js | 29 ++++++++++++++---- 2 files changed, 60 insertions(+), 20 deletions(-) diff --git a/Source/Core/ComponentDatatype.js b/Source/Core/ComponentDatatype.js index 01b1c96997f4..f13b4a3dff67 100644 --- a/Source/Core/ComponentDatatype.js +++ b/Source/Core/ComponentDatatype.js @@ -12,7 +12,8 @@ define(['./Enumeration'], function(Enumeration) { } /** - * DOC_TBA + * Enumerations for WebGL component datatypes. Components are intrinsics, + * which form attributes, which form vertices. * * @alias ComponentDatatype * @enumeration @@ -20,11 +21,13 @@ define(['./Enumeration'], function(Enumeration) { var ComponentDatatype = {}; /** - * DOC_TBA + * 8-bit signed byte enumeration corresponding to gl.BYTE and the type + * of an element in Int8Array. + * + * @memberOf ComponentDatatype * * @constant * @type {Enumeration} - * @memberOf ComponentDatatype */ ComponentDatatype.BYTE = new Enumeration(0x1400, 'BYTE'); ComponentDatatype.BYTE.sizeInBytes = Int8Array.BYTES_PER_ELEMENT; @@ -37,11 +40,13 @@ define(['./Enumeration'], function(Enumeration) { }; /** - * DOC_TBA + * 8-bit unsigned byte enumeration corresponding to UNSIGNED_BYTE and the type + * of an element in Uint8Array. + * + * @memberOf ComponentDatatype * * @constant * @type {Enumeration} - * @memberOf ComponentDatatype */ ComponentDatatype.UNSIGNED_BYTE = new Enumeration(0x1401, 'UNSIGNED_BYTE'); ComponentDatatype.UNSIGNED_BYTE.sizeInBytes = Uint8Array.BYTES_PER_ELEMENT; @@ -54,11 +59,13 @@ define(['./Enumeration'], function(Enumeration) { }; /** - * DOC_TBA + * 16-bit signed short enumeration corresponding to SHORT and the type + * of an element in Int16Array. + * + * @memberOf ComponentDatatype * * @constant * @type {Enumeration} - * @memberOf ComponentDatatype */ ComponentDatatype.SHORT = new Enumeration(0x1402, 'SHORT'); ComponentDatatype.SHORT.sizeInBytes = Int16Array.BYTES_PER_ELEMENT; @@ -71,11 +78,13 @@ define(['./Enumeration'], function(Enumeration) { }; /** - * DOC_TBA + * 16-bit unsigned short enumeration corresponding to UNSIGNED_SHORT and the type + * of an element in Uint16Array. + * + * @memberOf ComponentDatatype * * @constant * @type {Enumeration} - * @memberOf ComponentDatatype */ ComponentDatatype.UNSIGNED_SHORT = new Enumeration(0x1403, 'UNSIGNED_SHORT'); ComponentDatatype.UNSIGNED_SHORT.sizeInBytes = Uint16Array.BYTES_PER_ELEMENT; @@ -88,11 +97,13 @@ define(['./Enumeration'], function(Enumeration) { }; /** - * DOC_TBA + * 32-bit floating-point enumeration corresponding to FLOAT and the type + * of an element in Float32Array. + * + * @memberOf ComponentDatatype * * @constant * @type {Enumeration} - * @memberOf ComponentDatatype */ ComponentDatatype.FLOAT = new Enumeration(0x1406, 'FLOAT'); ComponentDatatype.FLOAT.sizeInBytes = Float32Array.BYTES_PER_ELEMENT; @@ -105,11 +116,14 @@ define(['./Enumeration'], function(Enumeration) { }; /** - * DOC_TBA + * 64-bit floating-point enumeration corresponding to gl.DOUBLE (in Desktop OpenGL; + * this is not supported in WebGL, and is emulated in Cesium via {@link GeometryPipeline.encodeAttribute}) + * and the type of an element in Float64Array. + * + * @memberOf ComponentDatatype * * @constant * @type {Enumeration} - * @memberOf ComponentDatatype */ ComponentDatatype.DOUBLE = new Enumeration(0x140A, 'DOUBLE'); ComponentDatatype.DOUBLE.sizeInBytes = Float64Array.BYTES_PER_ELEMENT; @@ -122,7 +136,16 @@ define(['./Enumeration'], function(Enumeration) { }; /** - * DOC_TBA + * Validates that the provided component datatype is a valid {@link ComponentDatatype} + * + * @param {ComponentDatatype} componentDatatype The component datatype to validate. + * + * @return {Boolean} true if the provided component datatype is a valid enumeration value; otherwise, false. + * + * @example + * if (!ComponentDatatype.validate(componentDatatype)) { + * throw new DeveloperError('componentDatatype must be a valid enumeration value.'); + * } */ ComponentDatatype.validate = function(componentDatatype) { return ((componentDatatype === ComponentDatatype.BYTE) || diff --git a/Source/Core/IndexDatatype.js b/Source/Core/IndexDatatype.js index 0284605af24b..7354908d37f7 100644 --- a/Source/Core/IndexDatatype.js +++ b/Source/Core/IndexDatatype.js @@ -8,13 +8,16 @@ define([ "use strict"; /** - * DOC_TBA + * Enumerations for WebGL index datatypes. These corresponds to the + * type parameter of drawElements. * - * @exports IndexDatatype + * @alias IndexDatatype + * @enumeration */ var IndexDatatype = { /** - * DOC_TBA + * 8-bit unsigned byte enumeration corresponding to UNSIGNED_BYTE and the type + * of an element in Uint8Array. * * @constant * @type {Enumeration} @@ -22,14 +25,19 @@ define([ UNSIGNED_BYTE : new Enumeration(0x1401, 'UNSIGNED_BYTE'), /** - * DOC_TBA + * 16-bit unsigned short enumeration corresponding to UNSIGNED_SHORT and the type + * of an element in Uint16Array. * * @constant * @type {Enumeration} */ UNSIGNED_SHORT : new Enumeration(0x1403, 'UNSIGNED_SHORT'), + /** - * DOC_TBA + * 32-bit unsigned int enumeration corresponding to UNSIGNED_INT and the type + * of an element in Uint32Array. + * + * @memberOf ComponentDatatype * * @constant * @type {Enumeration} @@ -42,7 +50,16 @@ define([ IndexDatatype.UNSIGNED_INT.sizeInBytes = Uint32Array.BYTES_PER_ELEMENT; /** - * DOC_TBA + * Validates that the provided index datatype is a valid {@link IndexDatatype} + * + * @param {IndexDatatype} indexDatatype The index datatype to validate. + * + * @return {Boolean} true if the provided index datatype is a valid enumeration value; otherwise, false. + * + * @example + * if (!IndexDatatype.validate(indexDatatype)) { + * throw new DeveloperError('indexDatatype must be a valid enumeration value.'); + * } */ IndexDatatype.validate = function(indexDatatype) { return ((indexDatatype === IndexDatatype.UNSIGNED_BYTE) || From 330ab4053d581c8598a5f1fd2cb0c1759f8cfc44 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Tue, 18 Jun 2013 11:30:32 -0400 Subject: [PATCH 184/306] Ability to change appearance and material --- Apps/CesiumViewer/CesiumViewer.js | 18 +++-- Source/Scene/Primitive.js | 128 ++++++++++++++++++++---------- 2 files changed, 100 insertions(+), 46 deletions(-) diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index 223d308ebe31..3a729818fdbc 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -325,12 +325,13 @@ define([ }), pickData : 'polygon3' }); - scene.getPrimitives().add(new Primitive({ + var polygonPrimitive = new Primitive({ geometryInstances : polygonGeometry, appearance : new EllipsoidSurfaceAppearance({ material : Material.fromType(scene.getContext(), 'Stripe') }) - })); + }); + scene.getPrimitives().add(polygonPrimitive); var wall = new GeometryInstance({ geometry : new WallGeometry({ @@ -345,7 +346,7 @@ define([ }), pickData : 'wall' }); - scene.getPrimitives().add(new Primitive({ + var wallPrimitive = new Primitive({ geometryInstances : wall, appearance : new Appearance({ material : Material.fromType(scene.getContext(), 'Wood'), @@ -355,7 +356,8 @@ define([ } } }) - })); + }); + scene.getPrimitives().add(wallPrimitive); var customWithIndices = new GeometryInstance({ geometry : new Geometry({ @@ -412,6 +414,12 @@ define([ }, ScreenSpaceEventType.MOUSE_MOVE ); - + handler.setInputAction( + function () { + polygonPrimitive.appearance.material = Material.fromType(scene.getContext(), 'Wood'); + wallPrimitive.appearance = new ClosedTranslucentAppearance(); + }, + ScreenSpaceEventType.LEFT_CLICK + ); } }); diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index ff843f877a26..0da514a96a4b 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -136,6 +136,8 @@ define([ * DOC_TBA */ this.appearance = options.appearance; + this._appearance = undefined; + this._material = undefined; /** * The 4x4 transformation matrix that transforms the primitive (all geometry instances) from model to world coordinates. @@ -173,11 +175,16 @@ define([ // geometry or all geometries are in the same reference frame. this._transformToWorldCoordinates = defaultValue(options.transformToWorldCoordinates, true); - this._sp = undefined; this._va = []; + this._attributeIndices = undefined; + + this._rs = undefined; + this._sp = undefined; + this._pickRS = undefined; this._pickSP = undefined; this._pickIds = []; + this._isPickable = false; this._commandLists = new CommandLists(); }; @@ -441,6 +448,10 @@ define([ return; } + if (!frameState.passes.color && !frameState.passes.pick) { + return; + } + var colorCommands = this._commandLists.colorList; var pickCommands = this._commandLists.pickList; var length; @@ -459,65 +470,35 @@ define([ } } - var attributeIndices = GeometryPipeline.createAttributeIndices(geometries[0]); + this._attributeIndices = GeometryPipeline.createAttributeIndices(geometries[0]); var va = []; for (i = 0; i < length; ++i) { va.push(context.createVertexArrayFromGeometry({ geometry : geometries[i], - attributeIndices : attributeIndices, + attributeIndices : this._attributeIndices, bufferUsage : BufferUsage.STATIC_DRAW, vertexLayout : VertexLayout.INTERLEAVED })); } - var appearance = this.appearance; - var vs = appearance.vertexShaderSource; - var fs = appearance.getFragmentShaderSource(); - this._va = va; -// TODO: recompile on material change. - this._sp = context.getShaderCache().replaceShaderProgram(this._sp, appearance.vertexShaderSource, fs, attributeIndices); - var rs = context.createRenderState(appearance.renderState); - var pickRS; - - if (isPickable(instances)) { - this._pickSP = context.getShaderCache().replaceShaderProgram(this._pickSP, vs, createPickFragmentShaderSource(fs, 'varying'), attributeIndices); - pickRS = rs; - } else { - this._pickSP = context.getShaderCache().replaceShaderProgram(this._pickSP, appearance.vertexShaderSource, fs, attributeIndices); - - // Still render during pick pass, but depth-only. - var appearanceRS = clone(appearance.renderState, true); - appearanceRS.colorMask = { - red : false, - green : false, - blue : false, - alpha : false - }; - pickRS = context.createRenderState(appearanceRS); - } - - var uniforms = (typeof appearance.material !== 'undefined') ? appearance.material._uniforms : undefined; + this._isPickable = isPickable(instances); for (i = 0; i < length; ++i) { var geometry = geometries[i]; + // renderState, shaderProgram, and uniformMap for commands are set below. + var command = new DrawCommand(); command.primitiveType = geometry.primitiveType; command.vertexArray = this._va[i]; - command.renderState = rs; - command.shaderProgram = this._sp; - command.uniformMap = uniforms; command.boundingVolume = geometry.boundingSphere; colorCommands.push(command); var pickCommand = new DrawCommand(); pickCommand.primitiveType = geometry.primitiveType; pickCommand.vertexArray = this._va[i]; - pickCommand.renderState = pickRS; - pickCommand.shaderProgram = this._pickSP; - pickCommand.uniformMap = uniforms; pickCommand.boundingVolume = geometry.boundingSphere; pickCommands.push(pickCommand); } @@ -527,16 +508,81 @@ define([ } } - // The geometry is static but the model matrix can change - if (frameState.passes.color || frameState.passes.pick) { + // Create or recreate render state and shader program if appearance/material changed + var appearance = this.appearance; + var createRS = false; + var createSP = false; + + if (this._appearance !== appearance) { + + this._appearance = appearance; + this._material = appearance.material; + createRS = true; + createSP = true; + } else if (this._material !== appearance.material ) { + this._material = appearance.material; + createSP = true; + } + + if (createRS) { + this._rs = context.createRenderState(appearance.renderState); + + if (this._isPickable) { + this._pickRS = this._rs; + } else { + // Still render during pick pass, but depth-only. + var appearanceRS = clone(appearance.renderState, true); + appearanceRS.colorMask = { + red : false, + green : false, + blue : false, + alpha : false + }; + this._pickRS = context.createRenderState(appearanceRS); + } + } + + if (createSP) { + var shaderCache = context.getShaderCache(); + var vs = appearance.vertexShaderSource; + var fs = appearance.getFragmentShaderSource(); + + this._sp = shaderCache.replaceShaderProgram(this._sp, appearance.vertexShaderSource, fs, this._attributeIndices); + + if (this._isPickable) { + this._pickSP = shaderCache.replaceShaderProgram(this._pickSP, vs, createPickFragmentShaderSource(fs, 'varying'), this._attributeIndices); + } else { + // Color pass shader, but rendered with depth-only for correct occlusion + this._pickSP = shaderCache.replaceShaderProgram(this._pickSP, vs, fs, this._attributeIndices); + } + } + + if (createRS || createSP) { + var uniforms = (typeof appearance.material !== 'undefined') ? appearance.material._uniforms : undefined; + length = colorCommands.length; for (i = 0; i < length; ++i) { - colorCommands[i].modelMatrix = this.modelMatrix; - pickCommands[i].modelMatrix = this.modelMatrix; + + var colorCommand = colorCommands[i]; + colorCommand.renderState = this._rs; + colorCommand.shaderProgram = this._sp; + colorCommand.uniformMap = uniforms; + + var pickCommand = pickCommands[i]; + pickCommand.renderState = this._pickRS; + pickCommand.shaderProgram = this._pickSP; + pickCommand.uniformMap = uniforms; } + } - commandList.push(this._commandLists); + // modelMatrix can change from frame to frame + length = colorCommands.length; + for (i = 0; i < length; ++i) { + colorCommands[i].modelMatrix = this.modelMatrix; + pickCommands[i].modelMatrix = this.modelMatrix; } + + commandList.push(this._commandLists); }; /** From a07ce2e6b493e3f40e2702e32d4017edc21c438c Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Tue, 18 Jun 2013 13:33:18 -0400 Subject: [PATCH 185/306] Fixed JSHint warning --- Source/Scene/Primitive.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index 0da514a96a4b..9f1415cd01bc 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -454,6 +454,8 @@ define([ var colorCommands = this._commandLists.colorList; var pickCommands = this._commandLists.pickList; + var colorCommand; + var pickCommand; var length; var i; @@ -490,13 +492,13 @@ define([ // renderState, shaderProgram, and uniformMap for commands are set below. - var command = new DrawCommand(); - command.primitiveType = geometry.primitiveType; - command.vertexArray = this._va[i]; - command.boundingVolume = geometry.boundingSphere; - colorCommands.push(command); + colorCommand = new DrawCommand(); + colorCommand.primitiveType = geometry.primitiveType; + colorCommand.vertexArray = this._va[i]; + colorCommand.boundingVolume = geometry.boundingSphere; + colorCommands.push(colorCommand); - var pickCommand = new DrawCommand(); + pickCommand = new DrawCommand(); pickCommand.primitiveType = geometry.primitiveType; pickCommand.vertexArray = this._va[i]; pickCommand.boundingVolume = geometry.boundingSphere; @@ -563,12 +565,12 @@ define([ length = colorCommands.length; for (i = 0; i < length; ++i) { - var colorCommand = colorCommands[i]; + colorCommand = colorCommands[i]; colorCommand.renderState = this._rs; colorCommand.shaderProgram = this._sp; colorCommand.uniformMap = uniforms; - var pickCommand = pickCommands[i]; + pickCommand = pickCommands[i]; pickCommand.renderState = this._pickRS; pickCommand.shaderProgram = this._pickSP; pickCommand.uniformMap = uniforms; From c94b21fa90f4f8c1065e9e6ba613c895480257e4 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Tue, 18 Jun 2013 15:09:37 -0400 Subject: [PATCH 186/306] Fixed ShaderCache false positive bug --- Source/Renderer/ShaderCache.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Source/Renderer/ShaderCache.js b/Source/Renderer/ShaderCache.js index 2aed6c6533e6..d83519e2f8c4 100644 --- a/Source/Renderer/ShaderCache.js +++ b/Source/Renderer/ShaderCache.js @@ -61,8 +61,7 @@ define([ * @see ShaderCache#replaceShaderProgram */ ShaderCache.prototype.getShaderProgram = function(vertexShaderSource, fragmentShaderSource, attributeLocations) { - // TODO: compare attributeLocations! - var keyword = vertexShaderSource + fragmentShaderSource; + var keyword = vertexShaderSource + fragmentShaderSource + JSON.stringify(attributeLocations); var cachedShader; if (this._shaders[keyword]) { From ce7a74c74d91999541bd681d32741d81f9324c01 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Tue, 18 Jun 2013 15:10:12 -0400 Subject: [PATCH 187/306] Remove no-pick optimization --- Apps/CesiumViewer/CesiumViewer.js | 8 ++- Source/Scene/Primitive.js | 95 +++++++++---------------------- 2 files changed, 33 insertions(+), 70 deletions(-) diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index 6e07d134d339..fb4e8ee6e538 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -27,6 +27,7 @@ define([ 'Core/WallGeometry', 'Scene/Primitive', 'Scene/Appearance', + 'Scene/TranslucentAppearance', 'Scene/ClosedTranslucentAppearance', 'Scene/PerInstanceColorClosedTranslucentAppearance', 'Scene/EllipsoidSurfaceAppearance', @@ -64,6 +65,7 @@ define([ WallGeometry, Primitive, Appearance, + TranslucentAppearance, ClosedTranslucentAppearance, PerInstanceColorClosedTranslucentAppearance, EllipsoidSurfaceAppearance, @@ -351,8 +353,8 @@ define([ Cartographic.fromDegrees(-120.0, 37.0, 100000.0), Cartographic.fromDegrees(-125.0, 37.0, 100000.0) ]) - }), - pickData : 'wall' + }) + // pickData is undefined here for testing }); var wallPrimitive = new Primitive({ geometryInstances : wall, @@ -425,7 +427,7 @@ define([ handler.setInputAction( function () { polygonPrimitive.appearance.material = Material.fromType(scene.getContext(), 'Wood'); - wallPrimitive.appearance = new ClosedTranslucentAppearance(); + wallPrimitive.appearance = new TranslucentAppearance(); }, ScreenSpaceEventType.LEFT_CLICK ); diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index 9f1415cd01bc..d6966336aebf 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -181,10 +181,8 @@ define([ this._rs = undefined; this._sp = undefined; - this._pickRS = undefined; this._pickSP = undefined; this._pickIds = []; - this._isPickable = false; this._commandLists = new CommandLists(); }; @@ -238,19 +236,6 @@ define([ } } - function isPickable(instances) { - var pickable = false; - var length = instances.length; - for (var i = 0; i < length; ++i) { - if (typeof instances[i].pickData !== 'undefined') { - pickable = true; - break; - } - } - - return pickable; - } - function addPickColorAttribute(primitive, instances, context) { var length = instances.length; @@ -268,26 +253,24 @@ define([ values : new Uint8Array(numberOfComponents) }); - if (typeof instance.pickData !== 'undefined') { - var pickId = context.createPickId({ - primitive : primitive, - pickData : instance.pickData - }); - primitive._pickIds.push(pickId); - - var pickColor = pickId.color; - var red = Color.floatToByte(pickColor.red); - var green = Color.floatToByte(pickColor.green); - var blue = Color.floatToByte(pickColor.blue); - var alpha = Color.floatToByte(pickColor.alpha); - var values = attributes.pickColor.values; - - for (var j = 0; j < numberOfComponents; j += 4) { - values[j] = red; - values[j + 1] = green; - values[j + 2] = blue; - values[j + 3] = alpha; - } + var pickId = context.createPickId({ + primitive : primitive, + pickData : instance.pickData // may be undefined + }); + primitive._pickIds.push(pickId); + + var pickColor = pickId.color; + var red = Color.floatToByte(pickColor.red); + var green = Color.floatToByte(pickColor.green); + var blue = Color.floatToByte(pickColor.blue); + var alpha = Color.floatToByte(pickColor.alpha); + var values = attributes.pickColor.values; + + for (var j = 0; j < numberOfComponents; j += 4) { + values[j] = red; + values[j + 1] = green; + values[j + 2] = blue; + values[j + 3] = alpha; } } } @@ -409,10 +392,8 @@ define([ addColorAttribute(primitive, insts, context); } - // Add pickColor attribute if any geometries are pickable - if (isPickable(insts)) { - addPickColorAttribute(primitive, insts, context); - } + // Add pickColor attribute for picking individual instances + addPickColorAttribute(primitive, insts, context); // Add default values for any undefined attributes addDefaultAttributes(insts); @@ -485,7 +466,6 @@ define([ } this._va = va; - this._isPickable = isPickable(instances); for (i = 0; i < length; ++i) { var geometry = geometries[i]; @@ -512,36 +492,23 @@ define([ // Create or recreate render state and shader program if appearance/material changed var appearance = this.appearance; + var material = appearance.material; var createRS = false; var createSP = false; if (this._appearance !== appearance) { this._appearance = appearance; - this._material = appearance.material; + this._material = material; createRS = true; createSP = true; - } else if (this._material !== appearance.material ) { - this._material = appearance.material; + } else if (this._material !== material ) { + this._material = material; createSP = true; } if (createRS) { this._rs = context.createRenderState(appearance.renderState); - - if (this._isPickable) { - this._pickRS = this._rs; - } else { - // Still render during pick pass, but depth-only. - var appearanceRS = clone(appearance.renderState, true); - appearanceRS.colorMask = { - red : false, - green : false, - blue : false, - alpha : false - }; - this._pickRS = context.createRenderState(appearanceRS); - } } if (createSP) { @@ -549,18 +516,12 @@ define([ var vs = appearance.vertexShaderSource; var fs = appearance.getFragmentShaderSource(); - this._sp = shaderCache.replaceShaderProgram(this._sp, appearance.vertexShaderSource, fs, this._attributeIndices); - - if (this._isPickable) { - this._pickSP = shaderCache.replaceShaderProgram(this._pickSP, vs, createPickFragmentShaderSource(fs, 'varying'), this._attributeIndices); - } else { - // Color pass shader, but rendered with depth-only for correct occlusion - this._pickSP = shaderCache.replaceShaderProgram(this._pickSP, vs, fs, this._attributeIndices); - } + this._sp = shaderCache.replaceShaderProgram(this._sp, vs, fs, this._attributeIndices); + this._pickSP = shaderCache.replaceShaderProgram(this._pickSP, vs, createPickFragmentShaderSource(fs, 'varying'), this._attributeIndices); } if (createRS || createSP) { - var uniforms = (typeof appearance.material !== 'undefined') ? appearance.material._uniforms : undefined; + var uniforms = (typeof material !== 'undefined') ? material._uniforms : undefined; length = colorCommands.length; for (i = 0; i < length; ++i) { @@ -571,7 +532,7 @@ define([ colorCommand.uniformMap = uniforms; pickCommand = pickCommands[i]; - pickCommand.renderState = this._pickRS; + pickCommand.renderState = this._rs; pickCommand.shaderProgram = this._pickSP; pickCommand.uniformMap = uniforms; } From 6ed0fb5fa63756b3313fc819d305e0e6d6c198ce Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Tue, 18 Jun 2013 16:29:47 -0400 Subject: [PATCH 188/306] Force transform to world coordinates if 2D positions are to be computed. --- Apps/CesiumViewer/CesiumViewer.js | 43 ++++++++++++++++++------------- Source/Core/GeometryPipeline.js | 6 ++--- Source/Core/PolylinePipeline.js | 2 +- Source/Scene/Primitive.js | 19 +++++++++----- 4 files changed, 42 insertions(+), 28 deletions(-) diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index 1eb2bb25aa79..4fb50d1afe22 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -175,10 +175,6 @@ define([ } } - - - - var ellipsoid = viewer.centralBody.getEllipsoid(); var geometry = new GeometryInstance({ @@ -281,8 +277,8 @@ define([ geometryInstances : geometry5, appearance :appearance, vertexCacheOptimize : false, - releasegeometryInstances : true, - //transformToWorldCoordinates : false + releaseGeometries : true, + transformToWorldCoordinates : false })); var polygonGeometry = new GeometryInstance({ @@ -367,18 +363,24 @@ define([ }); scene.getPrimitives().add(wallPrimitive); - /* + var positions = ellipsoid.cartographicArrayToCartesianArray([ + Cartographic.fromDegrees(-70.0, 20.0), + Cartographic.fromDegrees(-70.0, 0.0), + Cartographic.fromDegrees(-60.0, 10.0) + ]); + var flatPositions = []; + var p, i; + for (i = 0; i < positions.length; ++i) { + p = positions[i]; + flatPositions.push(p.x, p.y, p.z); + } var customWithIndices = new GeometryInstance({ geometry : new Geometry({ attributes : { position : new GeometryAttribute({ componentDatatype : ComponentDatatype.DOUBLE, componentsPerAttribute : 3, - values : new Float64Array([ - 0.0, 0.0, 2000000.0, - 7500000.0, 0.0, 2000000.0, - 0.0, 7500000.0, 2000000.0 - ]) + values : new Float64Array(flatPositions) }) }, indices : new Uint16Array([0, 1, 1, 2, 2, 0]), @@ -391,17 +393,23 @@ define([ appearance : new Appearance() })); + positions = ellipsoid.cartographicArrayToCartesianArray([ + Cartographic.fromDegrees(-70.0, 20.0, 200000.0), + Cartographic.fromDegrees(-70.0, 0.0, 200000.0), + Cartographic.fromDegrees(-60.0, 10.0, 200000.0) + ]); + flatPositions = []; + for (i = 0; i < positions.length; ++i) { + p = positions[i]; + flatPositions.push(p.x, p.y, p.z); + } var customWithoutIndices = new GeometryInstance({ geometry : new Geometry({ attributes : { position : new GeometryAttribute({ componentDatatype : ComponentDatatype.DOUBLE, componentsPerAttribute : 3, - values : new Float64Array([ - 0.0, 0.0, 0.0, - 7500000.0, 0.0, 0.0, - 0.0, 7500000.0, 0.0 - ]) + values : new Float64Array(flatPositions) }) }, primitiveType : PrimitiveType.LINE_LOOP @@ -412,7 +420,6 @@ define([ geometryInstances : customWithoutIndices, appearance : new Appearance() })); - */ var handler = new ScreenSpaceEventHandler(scene.getCanvas()); handler.setInputAction( diff --git a/Source/Core/GeometryPipeline.js b/Source/Core/GeometryPipeline.js index d3b779462e5e..30c407de20b2 100644 --- a/Source/Core/GeometryPipeline.js +++ b/Source/Core/GeometryPipeline.js @@ -762,7 +762,7 @@ define([ var k; var m = instances[0].modelMatrix; - var haveindicess = (typeof instances[0].geometry.indices !== 'undefined'); + var haveIndices = (typeof instances[0].geometry.indices !== 'undefined'); var primitiveType = instances[0].geometry.primitiveType; for (i = 1; i < length; ++i) { @@ -770,7 +770,7 @@ define([ throw new DeveloperError('All instances must have the same modelMatrix.'); } - if ((typeof instances[i].geometry.indices !== 'undefined') !== haveindicess) { + if ((typeof instances[i].geometry.indices !== 'undefined') !== haveIndices) { throw new DeveloperError('All instance geometries must have an indices or not have one.'); } @@ -805,7 +805,7 @@ define([ // Combine index lists var indices; - if (haveindicess) { + if (haveIndices) { var numberOfIndices = 0; for (i = 0; i < length; ++i) { numberOfIndices += instances[i].geometry.indices.length; diff --git a/Source/Core/PolylinePipeline.js b/Source/Core/PolylinePipeline.js index 77d78f6bf1cb..147a6414f1a8 100644 --- a/Source/Core/PolylinePipeline.js +++ b/Source/Core/PolylinePipeline.js @@ -121,7 +121,7 @@ define([ * * @param {Array} positions The array of positions. Each element is usually a {@see Cartesian3}, but all that is required is that the object have an equals function. * - * @returns {Object} A new array of positions with no adjacent duplicate positions. Positions are shallow copied. + * @returns {Array} A new array of positions with no adjacent duplicate positions. Positions are shallow copied. * * @exception {DeveloperError} positions is required. * diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index 1fda4321ba72..f2d45fa29d6f 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -61,6 +61,7 @@ define([ * @param {Boolean} [options.vertexCacheOptimize=true] When true, geometry vertices are optimized for the pre- and post-vertex-shader caches. * @param {Boolean} [options.releaseGeometries=true] When true, the primitive does not keep a reference to the input geometryInstances to save memory. * @param {Boolean} [options.transformToWorldCoordinates=true] When true, each geometry instance is transform to world coordinates even if they are already in the same coordinate system. + * @param {Boolean} [options.allowColumbusView=true] When true, each geometry instance is prepared for rendering in Columbus view and 2D. * * @example * // 1. Draw a translucent ellipse on the surface with a checkerboard pattern @@ -174,6 +175,7 @@ define([ // When true, geometry is transformed to world coordinates even if there is a single // geometry or all geometries are in the same reference frame. this._transformToWorldCoordinates = defaultValue(options.transformToWorldCoordinates, true); + this._allowColumbusView = defaultValue(options.allowColumbusView, true); this._va = []; this._attributeIndices = undefined; @@ -370,7 +372,7 @@ define([ } function transformToWorldCoordinates(primitive, instances) { - var toWorld = primitive._transformToWorldCoordinates; + var toWorld = primitive._transformToWorldCoordinates || primitive._allowColumbusView; var length = instances.length; var i; @@ -424,12 +426,17 @@ define([ // Combine into single geometry for better rendering performance. var geometry = GeometryPipeline.combine(insts); - // Compute 2D positions - GeometryPipeline.projectTo2D(geometry); + if (primitive._allowColumbusView) { + // Compute 2D positions + GeometryPipeline.projectTo2D(geometry); - // Split 3D and 2D position for GPU RTE - GeometryPipeline.encodeAttribute(geometry, 'position3D', 'position3DHigh', 'position3DLow'); - GeometryPipeline.encodeAttribute(geometry, 'position2D', 'position2DHigh', 'position2DLow'); + // Split 3D and 2D position for GPU RTE + GeometryPipeline.encodeAttribute(geometry, 'position3D', 'position3DHigh', 'position3DLow'); + GeometryPipeline.encodeAttribute(geometry, 'position2D', 'position2DHigh', 'position2DLow'); + } else { + // Split 3D position for GPU RTE + GeometryPipeline.encodeAttribute(geometry, 'position', 'positionHigh', 'positionLow'); + } if (!context.getElementIndexUint()) { // Break into multiple geometries to fit within unsigned short indices if needed From 02f982fad0b2dceb419f39c453e109371fe31772 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Wed, 19 Jun 2013 07:57:28 -0400 Subject: [PATCH 189/306] Procedurally add pick code to appearance vertex shaders --- Source/Scene/Primitive.js | 19 ++++++++++++++++++- .../Appearances/DefaultAppearanceVS.glsl | 3 --- .../EllipsoidSurfaceAppearanceVS.glsl | 3 --- .../PerInstanceColorAppearanceVS.glsl | 3 --- 4 files changed, 18 insertions(+), 10 deletions(-) diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index d6966336aebf..6c013e1ecfcc 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -378,6 +378,20 @@ define([ } } + function createPickVertexShaderSource(vertexShaderSource) { + var renamedVS = vertexShaderSource.replace(/void\s+main\s*\(\s*(?:void)?\s*\)/g, 'void czm_old_main()'); + var pickMain = + 'attribute vec4 pickColor; \n' + + 'varying vec4 czm_pickColor; \n' + + 'void main() \n' + + '{ \n' + + ' czm_old_main(); \n' + + ' czm_pickColor = pickColor; \n' + + '}'; + + return renamedVS + '\n' + pickMain; + } + // PERFORMANCE_IDEA: Move pipeline to a web-worker. function geometryPipeline(primitive, instances, context) { // Copy instances first since most pipeline operations modify the geometry and instance in-place. @@ -517,7 +531,10 @@ define([ var fs = appearance.getFragmentShaderSource(); this._sp = shaderCache.replaceShaderProgram(this._sp, vs, fs, this._attributeIndices); - this._pickSP = shaderCache.replaceShaderProgram(this._pickSP, vs, createPickFragmentShaderSource(fs, 'varying'), this._attributeIndices); + this._pickSP = shaderCache.replaceShaderProgram(this._pickSP, + createPickVertexShaderSource(vs), + createPickFragmentShaderSource(fs, 'varying'), + this._attributeIndices); } if (createRS || createSP) { diff --git a/Source/Shaders/Appearances/DefaultAppearanceVS.glsl b/Source/Shaders/Appearances/DefaultAppearanceVS.glsl index b53c37853f7a..7a635a6b7b6e 100644 --- a/Source/Shaders/Appearances/DefaultAppearanceVS.glsl +++ b/Source/Shaders/Appearances/DefaultAppearanceVS.glsl @@ -4,14 +4,12 @@ attribute vec3 normal; attribute vec3 tangent; attribute vec3 binormal; attribute vec2 st; -attribute vec4 pickColor; varying vec3 v_positionEC; varying vec3 v_normalEC; varying vec3 v_tangentEC; varying vec3 v_binormalEC; varying vec2 v_st; -varying vec4 czm_pickColor; void main() { @@ -22,7 +20,6 @@ void main() v_tangentEC = czm_normal * tangent; // tangent in eye coordinates v_binormalEC = czm_normal * binormal; // binormal in eye coordinates v_st = st; - czm_pickColor = pickColor; gl_Position = czm_modelViewProjectionRelativeToEye * p; } diff --git a/Source/Shaders/Appearances/EllipsoidSurfaceAppearanceVS.glsl b/Source/Shaders/Appearances/EllipsoidSurfaceAppearanceVS.glsl index b33700b32729..5c6ee213ac8f 100644 --- a/Source/Shaders/Appearances/EllipsoidSurfaceAppearanceVS.glsl +++ b/Source/Shaders/Appearances/EllipsoidSurfaceAppearanceVS.glsl @@ -1,12 +1,10 @@ attribute vec3 positionHigh; attribute vec3 positionLow; attribute vec2 st; -attribute vec4 pickColor; varying vec3 v_positionMC; varying vec3 v_positionEC; varying vec2 v_st; -varying vec4 czm_pickColor; void main() { @@ -15,7 +13,6 @@ void main() v_positionMC = positionHigh + positionLow; // position in model coordinates v_positionEC = (czm_modelViewRelativeToEye * p).xyz; // position in eye coordinates v_st = st; - czm_pickColor = pickColor; gl_Position = czm_modelViewProjectionRelativeToEye * p; } diff --git a/Source/Shaders/Appearances/PerInstanceColorAppearanceVS.glsl b/Source/Shaders/Appearances/PerInstanceColorAppearanceVS.glsl index 0226303cb52e..2d94f3efde91 100644 --- a/Source/Shaders/Appearances/PerInstanceColorAppearanceVS.glsl +++ b/Source/Shaders/Appearances/PerInstanceColorAppearanceVS.glsl @@ -2,12 +2,10 @@ attribute vec3 positionHigh; attribute vec3 positionLow; attribute vec3 normal; attribute vec4 color; -attribute vec4 pickColor; varying vec3 v_positionEC; varying vec3 v_normalEC; varying vec4 v_color; -varying vec4 czm_pickColor; void main() { @@ -16,7 +14,6 @@ void main() v_positionEC = (czm_modelViewRelativeToEye * p).xyz; // position in eye coordinates v_normalEC = czm_normal * normal; // normal in eye coordinates v_color = color; - czm_pickColor = pickColor; gl_Position = czm_modelViewProjectionRelativeToEye * p; } From fa76ed41ecd9216c968abb89957f4f333b454416 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Wed, 19 Jun 2013 08:02:57 -0400 Subject: [PATCH 190/306] Rename positionLow/positionHigh to position3DLow/position3DHigh --- Source/Scene/Primitive.js | 2 +- Source/Shaders/Appearances/DefaultAppearanceVS.glsl | 6 +++--- .../Shaders/Appearances/EllipsoidSurfaceAppearanceVS.glsl | 8 ++++---- .../Shaders/Appearances/PerInstanceColorAppearanceVS.glsl | 6 +++--- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index 6c013e1ecfcc..cfa1b88a6bf5 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -420,7 +420,7 @@ define([ var geometry = GeometryPipeline.combine(insts); // Split position for GPU RTE - GeometryPipeline.encodeAttribute(geometry, 'position', 'positionHigh', 'positionLow'); + GeometryPipeline.encodeAttribute(geometry, 'position', 'position3DHigh', 'position3DLow'); if (!context.getElementIndexUint()) { // Break into multiple geometries to fit within unsigned short indices if needed diff --git a/Source/Shaders/Appearances/DefaultAppearanceVS.glsl b/Source/Shaders/Appearances/DefaultAppearanceVS.glsl index 7a635a6b7b6e..d79dd5a5786e 100644 --- a/Source/Shaders/Appearances/DefaultAppearanceVS.glsl +++ b/Source/Shaders/Appearances/DefaultAppearanceVS.glsl @@ -1,5 +1,5 @@ -attribute vec3 positionHigh; -attribute vec3 positionLow; +attribute vec3 position3DHigh; +attribute vec3 position3DLow; attribute vec3 normal; attribute vec3 tangent; attribute vec3 binormal; @@ -13,7 +13,7 @@ varying vec2 v_st; void main() { - vec4 p = czm_translateRelativeToEye(positionHigh, positionLow); + vec4 p = czm_translateRelativeToEye(position3DHigh, position3DLow); v_positionEC = (czm_modelViewRelativeToEye * p).xyz; // position in eye coordinates v_normalEC = czm_normal * normal; // normal in eye coordinates diff --git a/Source/Shaders/Appearances/EllipsoidSurfaceAppearanceVS.glsl b/Source/Shaders/Appearances/EllipsoidSurfaceAppearanceVS.glsl index 5c6ee213ac8f..ceeef4445c6d 100644 --- a/Source/Shaders/Appearances/EllipsoidSurfaceAppearanceVS.glsl +++ b/Source/Shaders/Appearances/EllipsoidSurfaceAppearanceVS.glsl @@ -1,5 +1,5 @@ -attribute vec3 positionHigh; -attribute vec3 positionLow; +attribute vec3 position3DHigh; +attribute vec3 position3DLow; attribute vec2 st; varying vec3 v_positionMC; @@ -8,9 +8,9 @@ varying vec2 v_st; void main() { - vec4 p = czm_translateRelativeToEye(positionHigh, positionLow); + vec4 p = czm_translateRelativeToEye(position3DHigh, position3DLow); - v_positionMC = positionHigh + positionLow; // position in model coordinates + v_positionMC = position3DHigh + position3DLow; // position in model coordinates v_positionEC = (czm_modelViewRelativeToEye * p).xyz; // position in eye coordinates v_st = st; diff --git a/Source/Shaders/Appearances/PerInstanceColorAppearanceVS.glsl b/Source/Shaders/Appearances/PerInstanceColorAppearanceVS.glsl index 2d94f3efde91..2a42a9aa0dfd 100644 --- a/Source/Shaders/Appearances/PerInstanceColorAppearanceVS.glsl +++ b/Source/Shaders/Appearances/PerInstanceColorAppearanceVS.glsl @@ -1,5 +1,5 @@ -attribute vec3 positionHigh; -attribute vec3 positionLow; +attribute vec3 position3DHigh; +attribute vec3 position3DLow; attribute vec3 normal; attribute vec4 color; @@ -9,7 +9,7 @@ varying vec4 v_color; void main() { - vec4 p = czm_translateRelativeToEye(positionHigh, positionLow); + vec4 p = czm_translateRelativeToEye(position3DHigh, position3DLow); v_positionEC = (czm_modelViewRelativeToEye * p).xyz; // position in eye coordinates v_normalEC = czm_normal * normal; // normal in eye coordinates From 9b7302bddd5348017b4f7d9fa88a96ab0d0b473a Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Wed, 19 Jun 2013 08:40:50 -0400 Subject: [PATCH 191/306] Use semantics when assigning attribute locations --- Source/Core/GeometryPipeline.js | 36 ++++++++++++++++++++++-- Source/Scene/Primitive.js | 28 +++++++++--------- Specs/Renderer/VertexArrayFactorySpec.js | 16 +++++------ 3 files changed, 55 insertions(+), 25 deletions(-) diff --git a/Source/Core/GeometryPipeline.js b/Source/Core/GeometryPipeline.js index 1b59fe6b0eba..05a7c8ea309b 100644 --- a/Source/Core/GeometryPipeline.js +++ b/Source/Core/GeometryPipeline.js @@ -174,13 +174,43 @@ define([ throw new DeveloperError('geometry is required.'); } - var indices = {}; + // There can be a WebGL performance hit when attribute 0 is disabled, so + // assign attribute locations to well-known attributes. + var semantics = [ + // From VertexFormat.position - after 2D projection and high-precision encoding + 'position3DHigh', + 'position3DLow', + 'position2DHigh', + 'position2DLow', + + // From Primitive + 'pickColor', + + // From VertexFormat + 'normal', + 'st', + 'binormal', + 'tangent' + ]; var attributes = geometry.attributes; + var indices = {}; var j = 0; + var i; + var len = semantics.length; - for ( var name in attributes) { - if (attributes.hasOwnProperty(name)) { + // Attribute locations for well-known attributes + for (i = 0; i < len; ++i) { + var semantic = semantics[i]; + + if (typeof attributes[semantic] !== 'undefined') { + indices[semantic] = j++; + } + } + + // Locations for custom attributes + for (var name in attributes) { + if (attributes.hasOwnProperty(name) && (typeof indices[name] === 'undefined')) { indices[name] = j++; } } diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index cfa1b88a6bf5..17729d8e1caf 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -378,20 +378,6 @@ define([ } } - function createPickVertexShaderSource(vertexShaderSource) { - var renamedVS = vertexShaderSource.replace(/void\s+main\s*\(\s*(?:void)?\s*\)/g, 'void czm_old_main()'); - var pickMain = - 'attribute vec4 pickColor; \n' + - 'varying vec4 czm_pickColor; \n' + - 'void main() \n' + - '{ \n' + - ' czm_old_main(); \n' + - ' czm_pickColor = pickColor; \n' + - '}'; - - return renamedVS + '\n' + pickMain; - } - // PERFORMANCE_IDEA: Move pipeline to a web-worker. function geometryPipeline(primitive, instances, context) { // Copy instances first since most pipeline operations modify the geometry and instance in-place. @@ -431,6 +417,20 @@ define([ return [geometry]; } + function createPickVertexShaderSource(vertexShaderSource) { + var renamedVS = vertexShaderSource.replace(/void\s+main\s*\(\s*(?:void)?\s*\)/g, 'void czm_old_main()'); + var pickMain = + 'attribute vec4 pickColor; \n' + + 'varying vec4 czm_pickColor; \n' + + 'void main() \n' + + '{ \n' + + ' czm_old_main(); \n' + + ' czm_pickColor = pickColor; \n' + + '}'; + + return renamedVS + '\n' + pickMain; + } + /** * @private */ diff --git a/Specs/Renderer/VertexArrayFactorySpec.js b/Specs/Renderer/VertexArrayFactorySpec.js index 6d7b1c2149e7..d8031063858b 100644 --- a/Specs/Renderer/VertexArrayFactorySpec.js +++ b/Specs/Renderer/VertexArrayFactorySpec.js @@ -120,12 +120,12 @@ defineSuite([ it('creates a homogeneous multiple-attribute vertex (non-interleaved)', function() { var geometry = new Geometry({ attributes : { - position : new GeometryAttribute({ + customPosition : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 3, values : [0.0, 0.0, 0.0, 2.0, 2.0, 2.0] }), - normal : new GeometryAttribute({ + customNormal : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 3, values : [1.0, 1.0, 1.0, 3.0, 3.0, 3.0] @@ -141,14 +141,14 @@ defineSuite([ expect(va.getNumberOfAttributes()).toEqual(2); expect(va.getIndexBuffer()).not.toBeDefined(); - var position = geometry.attributes.position; + var position = geometry.attributes.customPosition; expect(va.getAttribute(0).index).toEqual(0); expect(va.getAttribute(0).componentDatatype).toEqual(position.componentDatatype); expect(va.getAttribute(0).componentsPerAttribute).toEqual(position.componentsPerAttribute); expect(va.getAttribute(0).offsetInBytes).toEqual(0); expect(va.getAttribute(0).strideInBytes).toEqual(0); // Tightly packed - var normal = geometry.attributes.position; + var normal = geometry.attributes.customNormal; expect(va.getAttribute(1).index).toEqual(1); expect(va.getAttribute(1).componentDatatype).toEqual(normal.componentDatatype); expect(va.getAttribute(1).componentsPerAttribute).toEqual(normal.componentsPerAttribute); @@ -161,12 +161,12 @@ defineSuite([ it('creates a homogeneous multiple-attribute vertex (interleaved)', function() { var geometry = new Geometry({ attributes : { - position : new GeometryAttribute({ + customPosition : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 3, values : [0.0, 0.0, 0.0, 2.0, 2.0, 2.0] }), - normal : new GeometryAttribute({ + customNormal : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 3, values : [1.0, 1.0, 1.0, 3.0, 3.0, 3.0] @@ -183,8 +183,8 @@ defineSuite([ expect(va.getNumberOfAttributes()).toEqual(2); expect(va.getIndexBuffer()).not.toBeDefined(); - var position = geometry.attributes.position; - var normal = geometry.attributes.position; + var position = geometry.attributes.customPosition; + var normal = geometry.attributes.customNormal; var expectedStride = position.componentDatatype.sizeInBytes * position.componentsPerAttribute + normal.componentDatatype.sizeInBytes * normal.componentsPerAttribute; expect(va.getAttribute(0).index).toEqual(0); From 727a991607cf21590f93243c951162f7316b537f Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Wed, 19 Jun 2013 10:30:35 -0400 Subject: [PATCH 192/306] Fix SkyBox --- Source/Core/GeometryPipeline.js | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/Source/Core/GeometryPipeline.js b/Source/Core/GeometryPipeline.js index 05a7c8ea309b..9fb0b6a1d8cd 100644 --- a/Source/Core/GeometryPipeline.js +++ b/Source/Core/GeometryPipeline.js @@ -170,6 +170,28 @@ define([ * @see ShaderCache */ GeometryPipeline.createAttributeIndices = function(geometry) { + + +/* + var indices = {}; + + if (typeof geometry !== 'undefined') { + var attributes = geometry.attributes; + var j = 0; + + for ( var name in attributes) { + if (attributes.hasOwnProperty(name)) { + indices[name] = j++; + } + } + } + + return indices; +*/ + + + + if (typeof geometry === 'undefined') { throw new DeveloperError('geometry is required.'); } @@ -177,6 +199,10 @@ define([ // There can be a WebGL performance hit when attribute 0 is disabled, so // assign attribute locations to well-known attributes. var semantics = [ + 'position', + 'positionHigh', + 'positionLow', + // From VertexFormat.position - after 2D projection and high-precision encoding 'position3DHigh', 'position3DLow', From 0fae5394dc51ff73bb19bc7e7fd7ad84324fdc90 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Wed, 19 Jun 2013 10:35:18 -0400 Subject: [PATCH 193/306] Fixed Wall Sandcastle example --- Apps/Sandcastle/gallery/Wall.html | 46 ++++++++++--------------------- 1 file changed, 14 insertions(+), 32 deletions(-) diff --git a/Apps/Sandcastle/gallery/Wall.html b/Apps/Sandcastle/gallery/Wall.html index 618509103b56..c5ff53037e8a 100644 --- a/Apps/Sandcastle/gallery/Wall.html +++ b/Apps/Sandcastle/gallery/Wall.html @@ -4,55 +4,37 @@ - + Cesium Demo + - - - +

Loading...

+ + + + + +
+

Loading...

+
+ + + diff --git a/Apps/Sandcastle/gallery/Wall.html b/Apps/Sandcastle/gallery/Wall.html deleted file mode 100644 index c5ff53037e8a..000000000000 --- a/Apps/Sandcastle/gallery/Wall.html +++ /dev/null @@ -1,125 +0,0 @@ - - - - - - - - Cesium Demo - - - - - - -
-

Loading...

-
- - - diff --git a/Apps/Sandcastle/gallery/Wall.jpg b/Apps/Sandcastle/gallery/Wall.jpg deleted file mode 100644 index df0b0f892e813852f11f133f4119cf54b48bc686..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12043 zcmb7qbyQr*ARG<@0@$y zyX)S6UQO>^wY#c&?Y&l2ch#@wW$9%T0G5$_F9`qwfdD;#E&%ZI48Rq0HaB)PHzWUO z?P^6X^5I1o+{ zKzMB6%K+dt002b%`w9OcAOP;~J0c;&v_vq?KlC3h00;+p4uB9NRyxd|o?0t3MCSPX+-HfB;c&5VkVN)M5V+ zsaV+|=42!5aNE%GJG>f3K)x^lp-cs;3>F0!kcd0GZ^RrpeQe$50w9$EU<1{F2-0HW zELNefahv%KrDA=%Su2nN;Dz&rLxn}r>7l6LSkPup!nT)Q!s&yN6@XJ1K&}!f0}3J! zp$rOfROq-65Y)Tn?-hm@2B-i6pdboRFaq>70j;XXa~}VrpAjHXSQJo(3J#%X3Bjft zmfWxVF2ZrlC$@Qf$=o<0f)gJ>5iA2P7X_CQY#<-jcahCX#O2GpAVLrrekajaY`Up0uS$v_$VmuYpVXw5DO8VT%9GB@cNvWOnbuzuQ z%YAR{`$yK9QeKM{FZ?FEvhfKu*{D2fF4~S-mcI2?37X7AKGT^+0nbJ@nFI>!W|E1_ z5Zgv}@IV2pbt`81Y0q~$7hgq#ly8Isrx+!g%+im+>=$sHaWoA5czoQ|(H?(ynm>{#Nin3nLH+}_D^F-!5zw7k9= zOE;g6daFC%T$8S#`MJUK67R9zjgjuKRJRiFL5g8bBx+Uhv&Kv=dX&< z`kHtH*Ls(WEU$%Nb~i91A@gF5D~84WaD-)3ZGG{-sE4*xcj&I;^CXeMHDfFIyI*Y6&Lld zHd167&-VY#>|fSdX_aNAg}d}TcaLT|k-TqyT53K!57E%jQ2)PEnhZwE$;m0yKmCGf z{&%9)e)j&mCjIYJ{Q?lGTKK@3IbqSL{l5ur8`Cx%nesGA?~7-w|EIwD8hIu3D%WMw z^E>Z8|8V*hsp+_99P8eHMBWl~B9oa3#@UcRQt_9h>_Z-L*xUTHA?La9Jsw!VO@8E% z^OWnvW{uqZX$qosqs#A%+mk#(v$fD+=#4$c<1neOb0Ai=vhHz{$<=lL7kDLu@fh63 zipZtx(h;=>iaaVo=?m|7@gJ=Q1(jxMn|z;@=~0#ylLksh%99nmV#N0j)D#rsoCe!# zc2?x6SH!o7mIhMay}QE6!`b*$sr7}@v-2%goYiQGg!fre^3%oK12GAExOha_NHKm) z86#4&Dntx{F*M!n1u$KCLgAa;JKIR@{B`hXUy6vL%IdASR*O}99JHO+RgD2ZVdTI> zdY&rM)LEN@GKO0`_S2kGulg-e|3dC8m6#jP0e{G<}R3izLA>B-IF(K9XDW>1L z5ZfgB1z=5;Q1xMkr@^K&QgA0_66bAMj1=!hJ96U(CrQ-Zq4x%HHY58-WT?$2*A=#z zt2i5Bk#W*Tp0twQ>(^#8azEpqmXqFKwr#K{o|#a2DgV;3=!Dca5U3$gq4ciFQ31Td?0K~PujLBdJU;xLBO&%<9Ww!Q-MC88<)V~Ob4O^UWpsZkAJP~C?3N~S5rvy=zdh&waX-MGKKg$$6 z5GVw^tW-g0z)>l#NPjc!X@{``v7;n5ZL%%x`?@9w**iF|<(3Nd?BHjZnBFo_e>0__ z5htTn({gsmL+szQ`S$TOMz@H{p_VoRSmggUk~sMv755Q8tMI0s9vz>Dh`-EWOoWR$ z8Bc9hdA)v{CKlfCTlQO&*UZrifCkCP;xwz#ePV@MZjHE&h0@hN=0}IcVOER%II`I) zBeUAVsanr(oP!6fx|*l(rDSHTOaF)uiX*?-n(ut#8moELm3s_4HI=PpKex*3ob-v? zMnXWhv~$TrQ@ipRiK7;_;fp4*65LTX9A%|V^pE9q-CFYps#cZfbFz@?59zg>Y2lxi zTVbz4m65ei#2oT&LjP4CPv*_omcJCldftaJDn{pCth@Q9HuMj~Jx1U14=OBHzvcaa zG0)v@WMZ$%Dfh*W1-Iv+?efgZH;sKya>)xL(C2VO?kpXS$_Jifzfv+AzIuMSGuGc( zUClyCANe;%`)3B-8@XMXq}+2bugJ<%hu-7nj!?*>hb>blHGVbmW@i<7=kkX|<_E&t zwunUXflyeU#*wUvVg@EEu2}JT{qKain8teR=Kj&-5}6SGZM>%>}6Eteh>m-SW-jouJC0+89E50}dI?2QjB0TL1+Qo0eaWF4sz=rLhaER~- zaImEE-(Cub4UYqJQK&L2n+O8AurZ4$g^JVpKkf$}(;h zl{0#3XNJ+`Z;*0|%9_V$az4#lQu>l`RSzoMJh;7E{5f}Kn5Nq4r>}6+_n!8Al$wb9*kh@AL+eQ`nuenvt?tFQolfOs$Ruk<$ouywC)dxZiZ}nmven`YF*4^in!zexiBdM_{t)FA{nMv7tvO#I@ws`g zd8jo>Bdq*$NuH#yAXp+fnHu&6vUAx~iE68>t3e?0pgBenEpcOzDBf@4m}1ZmMx4Z2 zagH-XI4@0RRhh`&&;-S?=nlG0Gr5pIa<{H^I%Q|`tl3r%jxo;ZO((# z4UfV~wjV!5?N0bpv}@LooplK`C}0PBtD?|ukcEM0fADZOv&NZ4wNK@l8S~icq?aX% z5O5b_7S6rLNuyRTk@$3XEmA#hB2ZXt6r<|o{>sEL&IC2Y(G7y86zocibelgKse;)l zt6cshQhI^F!!|uMzWV$=EfQp%n@w3ONdeRa7*rE$>j;)+3}u z@q&4~FX^&Ix^ncE3@Pat_}-W+$hBU+rH{R&enp#L-MOZwV^e0mHd^|TMywqt=z$Gy zP0 zOfF{Hck%CJ4oL{^QmKpAcUir<%nQG_^`q=}hjoV?%w>hn;VslKYscndm+Idgs5KF8H5J{Q+zHf0m_A95rju zW=#DrA&Jv?!`x&!XN>ma+vC;FG0x1XKe(DPvnPYb243Y~uC)aAAI&}gj1{TfV$J)^ z+iyKq(W%ka8y9?Oe*U>ld-gjm;subj`c)dUwHD&AVLgNn{JctIEc*jf00WW2NodpX9b(!oGxzy|Yd3oBeP@)^+k@0CR3T34 zi6c$nXWatVmNs+^ob`F?mAl^y1kUZQah|&8yNv=WpZoac#LP)aWRXaJM(9%re(yAS z0gSrZ>k|up>#1VZCwxi-$NS2BTIEt@H=Sa2>Be@a=fF+*3t+C4V>W%m<}F?($q=|HwZ&LM)xiY8;1)Y8nnA0N%1&6my?2`} zLSQ7&<#Z<#+1`UF;}%b{5_>h6owo-Kj(}~zqC2V;kvoX3XSbl}^z9e@h1NDlB-JPz zopq?OdWbLe6y}lhRIC9?*&6vC(JDX-?V+uZ3^R|L+A4Si5i4>Rl4M%y%;=)`izx+e z_48gt$Pxm{?wOR$Y$|UVyt{QkXJ5_DRqQF9&QX9lzj8xSu5SDALYL?5c`{j)mSfIH z7>;hg^MZEZZUj*&Zrf%x5B{%-_i+uO+q~5oZD(TY(A9dS+thX|zsSly!?}WLX8NOA z3`*ygz_4aCQ!OW^vMII9u!q&i&wa=lV16e7!p-G}~q3G#%qIPTO(mLAX6` zHOKKv1L}56`YlFx749Mr_C8}m8pE7HmCwtc8%YLsTWnrQWfA0?FS;NjNaQ=CBe=g= zhdiWG!WQKoYnbNz+-p#4v>s)!4M6pe=dUvHORm`*uP;_3u zBPrl1QYmp>+!ivTkK%!$VQ{SD>b}EtYkR1X$6r%k#RS?+@cify=?}X`s$eGINa*EI?@sx05ptZR zvg}CaZsI(l;f?qXzW;r>632HNBfnTWg5F84M6-(twKfSZv?v?353&gRW+M}X(MU#n zHBNnY^2WoNnJuX~IY|i`X|mi51c+^$yYwALaxI38+5YA_60E&FCyxn;<82NEz||~* zppse)hJ7M$qnd2&ps7w=b+{8Bl0T&o>k3__q@%lnE!H+k_&d6mL#l0-KWFMIy=jUn zO|mGsji`HBQK6ypnTxx?k#EJz&G7R4T5GZx?Xf7o$~7)e_mVt+_OmB0SDBJ=II#Is z-F`~rh_~~mQiLev*pat4UD&F^;ith>+oXs&I7RPyIFDjiQM#Y4-vo~_+eW(zE`LVd1`v0@RQOQdksV;Sj|Sv7FP~K@`$8C^t@2yp*232+YTYSYqdBZ-ILCRp zy*BHkn^`^XmygVI^!P0fSzKYPnNx9p&KdL=83!g5)b~z<&&h=^{*}hV&;}vs)8MOXVE~XIjFg7Nl!zgeIwiy& z2**JsF3bR`-vkiQY+I%-u>hiD1gxT1iwiLjpbn%-H}Cwb-~fOy*|dcJ z)@4&uIFlNaM&$U?GDpr|M`;KWO#PM&4-5aNh5e=Q@bH~6F+n9d=g@J#Ena_+|KNSH z{{fBO*SH2Vle3)z_*Ib1sJl-_G7k>i<`qa|l}ga))^W{X5SbnQR2uENvoN&rrgc+; zhj$4t7~X4HCyDPpv@u=`om-=KD0ssip?3NrLuH*HfeDE-9>o4s#1LsZ$uS6y z=64d|F`YK8gacDl<4uWZf$&v6VS9@#G9o%Guivpir}Cs5KpTI`A)GR2+e5&rMln`o z8td5V!3!oRrqLNnZx^ z9w&g_xwW_lmJJ0Kzw0x%Kd(n~sug(wprgwiGWSHnPidb5n8nGHHMoVzz>(%$((zIs zoW?Ly&H!*M5QIF4<*JDIr`i5Qr)4~-Q=I_CPvK&b^BgOB%L{^;|a?{1TWygN2pzyko z(Y#q0$})E&)MWy`?OEN5nj#q+ua%yA%zHF)C5^ZXi$np?cdyfm47N5^NTVfO(XcNT z2uL5ZGz5TY%S?~(q9JyAMRy2aaS-gb^MjLFC$QQNsvOtZu*OtcKrA%gLQ1$JIBWv5 zE?<41()rh%?io-jKpKW-NxpZ*z@0G9BBN2sPEZ*gdO$&2~qY7?Ksk0^as@b{9a5JJH46%dK{aws+)07{jQ*@%-J_)LTI-30W!e2Y}tg>b1 z8>MqH1!1*qaDG%|k`tX#aXI?yE)j>>H7E z;$z2RUUFp`<4Rx;kjOD0q6$2-6lO$U6}0hGrkYYzC)rhq0uT@|YT+Ob;C>7SOW2~_ zhJvST125L`z6kda08awqWLEWc0CWO>P~3`r*x0-T!w`@r0%XBUr>@~X1NddUq;;x| z7s6UH!8zKO*BOjGs6P(un=wC;SI&_raN~I&kmqu>cLIGG(XYNuzRLAx%O% zfg`Hc^wV~nk0$Z(qJV15fHef|Up#MIxeq?gfOqORi!kCO4(2@RjNvJgCGNOmMp27} zU0GJi&m&J72C zp4wQmhAd@Ck^suVE`GTv1{wle#yjf8h?$cNw)jxhDq2*`pgx^JE4Gb6i56j(+^$w2 zz!p}b@+>U^l!~WLq7`A)+&`yTfWHtKShbz|DbbFmX=ZN6U6{-6xmB2U!n^+@vVmJZ z(vN+oHNU&5#V|4Kj5gI`1l;llv8lINptHqzeRkH!vsRdE3Lrv`(h_L0VUaYj;*rBy z((f}u-tT>jyHwyFd1Ru}L34_?5aPhF--(?ds&vlwHYg!3^ez_~*8ZnoXngd}1c6+I zF+!=hqU-z906fAyRQSpS#!PiI$7;?4in!p5GQrgbEDC3h_w!bYyFFuy+ufr1omp(qDy zs5bpY=hn50WF`)e1`4V_G5k+G@tQTre)ROIn zYAWpS>I$5Vq|`|!8#?a3?iOwPP1n84IX7@hkdc?*HI242__PEKT_AH(C8Hx&os?NCp12bE2`)*x$pwQD>vy2_Y0o0T%@g95DtMi z-+m0Yt=}+@Iz=Z&^x!emWMn>mn%>v~r8*X#S1ij8J!fk1O5X||afcgi|ndzV#y)3&Z})yOu%ias)y^7D@LXGMnJ#)sj7wrmKc zNb$E_rZFiftcLr@<4HNxdPAvm*w})Sl@eu3%W-gu@JL$cR?+$*;NEkt(fG+rNH0LYjA;SDc<@P_ZOLo+nkvH0H$^&#!*ne_J)$-&1b zkjCXT#L7>)tFkU@Y(#f#g!Tv|87v#>9X(Pq-RjTig|S|;Sp#P)0%wvNEq7x|c%*-z zWwT^gj$1G;_7ep%?d2Hfk|!`c_CQ>CM}K%^1Am3@?1B*K(Wv$`M0M~d$)ai*G6O#LgTBvNa>M4D)47gj@Zpb zgNtLV5!)sX?uwHWD((_)Wa(xzBh!XSRJnLAe-3XUx*fEPmTeoV zFzSU-w#K^nT5a|23rWblDREicFB`;AQ~po3pTNs+Dl{&$A!Y~0JsMed$f|I^&d$ z+aK2nElm#|aV88Vil}dUh3fhc+D(~=#YE-pCBK<9v1m#h@L12zt%k~C;k)$iQyu50 za|QR;nbQPk?wiQ8oL`gKpeqYvIl+MmW1n4`VrDG zod)8v#TC%uGK}fkS#Xs^UZb-j1;3w}K|?-7a-&La-c59n-$FHb0U)sSql1enQ4pfp zH#T!&&v*AYclWg2y#mk3c^G&81?25y|5U)Rz=4Ai@V|Dqe=1;Q5n~u`3xjOW!M)QL zpNALITib<}Kgt z_DDltyN{Yn)6F=}ey+MS4vqaemg-}A968MNYC&k%N9Z28^xja*Y&?YV43)s`RWTxh zU6<{inPxNGz)4{oE=hoAO?K-Xd;nlNU_B(BLN)ITbOEGq+3xsg8b15F{eCCq1rXzw zvf$&g6JA5M!)8F*W_H~_i%!7u*zed??`!fnyhx_!%f1u)WO|tQ`hI^H_D=+K0d|-* zY5PV0B9bT+zw#IFx@c` zEB|>ZK+{n|q2FN^mB6||s+xa!$?E45^9tFpGogwEmIqJd=BrzFFXRfcE*$9B#yq}u z`&Vm!>PHt9{)E3;zW$7{)wzk%;8QJ2T0BwQC8s#}gsDeq<9e-{7d@qE(Kjg{9qPjn zT%jj|^TAc~$D=|6fznB?&(zKWmGYY=@2L-GRgy}OVttP||4Ddn-6dbl`uI$%Y!wWN@Iz2JYGtmcVJ z*CD;Xi_Vv4BpcZjL(XBpWi6sRoE0>s)C{u|ESHN#hI2}2V)|m6JNfzXVNhgDTHp{% zfQLy`nJ@>ko?jEbt&W}QvT>01x9jWmP_?tk8QKz zbOwFp+ZbZ!axvtAblu$r1lASomSYGKD-us?eL}&KvM$v#kvsTWeaZKDGeoLxjN*W% zI4XFFv>u>*6#e8B_Q5Mu&=pJ2?wFx%Cct88?k4zsfl}~x#l`GZgs^1?L~6P#+X<7% zKM3nCD4X$pSvpcp%ChGNLv~uhJiTzF2eepQ)S5~(gsb8gfK$FGqrOAJg(IAqU~Q^- zLA<+ZNAmAnmR@nlT}#Zt-K3T|#=WEAYs0TRUl6QosR!;Tex~gTB-IjHm0@Xxu2>Y` z43WEMN8+o0PW`!~w~yAW4yNOX$?|aus>dW>$P@TJOe(Jv@G}r-;_l2$_|E7u92-f< zIGG{-2w;VNABGzz@`*na8P~wahzl?$@+GNv#ou;1{F626^z2nwa-!5xh@wUP7EiOmHUL|mi^84h)Vvm74m_d=`gNMjAMfk)W7w1Ww@Zo(J4HfRJz{c`G--3ZhxJf^f z)Q~~v9i(Z$j=5gH+7M;9^J_5S%ecOH+6$~+M^lgd*n7?{O>m45z-h=qg9Xmj1vN3F za5>PGDgdt&JqY!4t+uRpGrw~01K*$)^S6fUxx|~aR^bfpMq}|ChrSYikBXt1G=#Dg zP<>J6FvoH&B0j)p>l2sDuIiV{g}9=KH({=W|M(j3+JORq!sRWy9UO6Cf*yk#WkSqN znMz6vKJTW8(y$AA zp}+=*T)hsfo@ColA_cT#5M>1Or-$;Z-(v?Jg!#C_Hi0c`Vxlq#O1ijFwNIwcaEXPe z0!=5p94o$b@$h4Bx$vr-096z{=Y4ZbO#&k^a{12cBD{DuACYMzT;${RGhgAnD<_A0 zD`s=$zD~mfma*d?#e@Ecl{r^<OU>jK7NGpDmERNyAKDRgaV;Ahb$yR? z$jiI?M;Id}T(-RxR~MZ_)$*fr&m~4JJbcrHAz`6Z?Aas-lmsPbP4mkY>yb3~aM1#G#Rkq|*6$b3C9R-CS!h5o8t?6QX2Hb+| z_J%uK%s9%Upb0!vp&g;RfsV-lX7usvycrw zU?EsXty3+%)8Zg3HstiM4*Xz6C6Hw>9;8P<<;EfW0tg);Ii7Mblh*SXHTqH(p#Bx< z*H)N0PGE_C$d-+gQvQ$zPrtT{-iY`kc5ajiUWxtc8h|;d(UT+ Date: Thu, 27 Jun 2013 19:42:29 -0400 Subject: [PATCH 255/306] Fix after merge. --- Source/Scene/createTangentSpaceDebugPrimitive.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/Source/Scene/createTangentSpaceDebugPrimitive.js b/Source/Scene/createTangentSpaceDebugPrimitive.js index a8a8fb2a0718..0e221b734b40 100644 --- a/Source/Scene/createTangentSpaceDebugPrimitive.js +++ b/Source/Scene/createTangentSpaceDebugPrimitive.js @@ -2,6 +2,7 @@ define([ '../Core/DeveloperError', '../Core/Color', + '../Core/ColorGeometryInstanceAttribute', '../Core/GeometryInstance', '../Core/GeometryPipeline', './Primitive', @@ -9,6 +10,7 @@ define([ ], function( DeveloperError, Color, + ColorGeometryInstanceAttribute, GeometryInstance, GeometryPipeline, Primitive, @@ -53,7 +55,9 @@ define([ if (typeof attributes.normal !== 'undefined') { instances.push(new GeometryInstance({ geometry : GeometryPipeline.createLineSegmentsForVectors(geometry, 'normal', length), - color : new Color(1.0, 0.0, 0.0, 1.0), + attributes : { + color : new ColorGeometryInstanceAttribute(new Color(1.0, 0.0, 0.0, 1.0)) + }, modelMatrix : modelMatrix })); } @@ -61,7 +65,9 @@ define([ if (typeof attributes.binormal !== 'undefined') { instances.push(new GeometryInstance({ geometry : GeometryPipeline.createLineSegmentsForVectors(geometry, 'binormal', length), - color : new Color(0.0, 1.0, 0.0, 1.0), + attributes : { + color : new ColorGeometryInstanceAttribute(new Color(0.0, 1.0, 0.0, 1.0)) + }, modelMatrix : modelMatrix })); } @@ -69,7 +75,9 @@ define([ if (typeof attributes.tangent !== 'undefined') { instances.push(new GeometryInstance({ geometry : GeometryPipeline.createLineSegmentsForVectors(geometry, 'tangent', length), - color : new Color(0.0, 0.0, 1.0, 1.0), + attributes : { + color : new ColorGeometryInstanceAttribute(new Color(0.0, 0.0, 1.0, 1.0)) + }, modelMatrix : modelMatrix })); } From 83f58347c1209e8457b36451d8166c03951599b5 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 27 Jun 2013 21:32:31 -0400 Subject: [PATCH 256/306] Compute each geometry's vertex buffers and offset/count in the buffer. Add property getter/setter to change per-instance attributes. --- Apps/CesiumViewer/CesiumViewer.js | 21 ++++- Source/Scene/Primitive.js | 123 +++++++++++++++++++++++++++++- 2 files changed, 140 insertions(+), 4 deletions(-) diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index 5c3819d4f0c1..cc864f635c11 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -208,7 +208,7 @@ define([ CesiumMath.toRadians(50.0), CesiumMath.toRadians(180.0), CesiumMath.toRadians(90.0)), - //granularity : 0.006 // More than 64K vertices + granularity : 0.006 // More than 64K vertices }), id : 'geometry', attributes : { @@ -522,6 +522,7 @@ define([ scene.getPrimitives().add(pp); var handler = new ScreenSpaceEventHandler(scene.getCanvas()); + /* handler.setInputAction( function (movement) { var pickedObject = scene.pick(movement.endPosition); @@ -531,8 +532,10 @@ define([ }, ScreenSpaceEventType.MOUSE_MOVE ); + */ handler.setInputAction( - function () { + function (e) { + /* polygonPrimitive.appearance.material = Material.fromType(scene.getContext(), 'Wood'); wallPrimitive.appearance = new MaterialAppearance(); @@ -543,6 +546,20 @@ define([ pp.material = Material.fromType(scene.getContext(), 'Dot'); pp.textureRotationAngle = CesiumMath.toRadians(30.0); pp.height = 1500000.0; + */ + + var pickedObject = scene.pick(e.position); + if (typeof pickedObject !== 'undefined') { + var attributes = primitive.getGeometryInstanceAttributes(pickedObject); + if (typeof attributes.color !== 'undefined') { + attributes.color = [ + Math.floor((Math.random()*100)), + Math.floor((Math.random()*100)), + Math.floor((Math.random()*100)), + 255 + ]; + } + } }, ScreenSpaceEventType.LEFT_CLICK ); diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index 53a7e4713f9f..db35f360de9d 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -409,6 +409,79 @@ define([ return geometries; } + function computePerInstanceAttributeIndices(instances, vertexArrays, attributeIndices) { + var indices = {}; + + var names = getCommonPerInstanceAttributeNames(instances); + var length = instances.length; + var offsets = {}; + var vaIndices = {}; + + for (var i = 0; i < length; ++i) { + var instance = instances[i]; + var numberOfVertices = Geometry.computeNumberOfVertices(instance.geometry); + + var namesLength = names.length; + for (var j = 0; j < namesLength; ++j) { + var name = names[j]; + var index = attributeIndices[name]; + + var tempVertexCount = numberOfVertices; + while (tempVertexCount > 0) { + var vaIndex = defaultValue(vaIndices[name], 0); + var va = vertexArrays[vaIndex]; + var vaLength = va.getNumberOfAttributes(); + + var attribute; + for (var k = 0; k < vaLength; ++k) { + attribute = va.getAttribute(k); + if (attribute.index === index) { + break; + } + } + + if (typeof indices[instance.id] === 'undefined') { + indices[instance.id] = {}; + } + + if (typeof indices[instance.id][name] === 'undefined') { + indices[instance.id][name] = []; + } + + var size = attribute.vertexBuffer.getSizeInBytes() / attribute.componentDatatype.sizeInBytes; + size /= attribute.componentsPerAttribute; + var offset = defaultValue(offsets[name], 0); + + var count; + if (offset + tempVertexCount < size) { + count = tempVertexCount; + indices[instance.id][name].push({ + attribute : attribute, + offset : offset, + count : count, + value : instance.attributes[name].value + }); + offsets[name] = offset + tempVertexCount; + } else { + count = size - offset; + indices[instance.id][name].push({ + attribute : attribute, + offset : offset, + count : count, + value : instance.attributes[name].value + }); + offsets[name] = 0; + vaIndices[name] = vaIndex + 1; + } + + tempVertexCount -= count; + } + } + } + + return indices; + } + function createColumbusViewShader(primitive, vertexShaderSource) { var attributes; if (primitive._allowColumbusView) { @@ -532,12 +605,13 @@ define([ for (i = 0; i < length; ++i) { va.push(context.createVertexArrayFromGeometry({ geometry : geometries[i], - attributeIndices : this._attributeIndices, - bufferUsage : BufferUsage.STATIC_DRAW + attributeIndices : this._attributeIndices//, + //bufferUsage : BufferUsage.STATIC_DRAW })); } this._va = va; + this._perInstanceAttributes = computePerInstanceAttributeIndices(insts, va, this._attributeIndices); for (i = 0; i < length; ++i) { var geometry = geometries[i]; @@ -639,6 +713,51 @@ define([ commandList.push(this._commandLists); }; + Primitive.prototype.getGeometryInstanceAttributes = function(id) { + if (typeof id === 'undefined') { + throw new DeveloperError('id is required'); + } + + var perInstanceAttributes = this._perInstanceAttributes[id]; + var attributes = {}; + + for (var name in perInstanceAttributes) { + if (perInstanceAttributes.hasOwnProperty(name)) { + Object.defineProperty(attributes, name, { + get : function () { + return perInstanceAttributes[name][0].value; + }, + set : function (value) { + if (typeof value === 'undefined' || typeof value.length === 'undefined' || value.length < 1 || value.length > 4) { + throw new DeveloperError('value must be and array with length between 1 and 4.'); + } + + var indices = perInstanceAttributes[name]; + var length = indices.length; + for (var i = 0; i < length; ++i) { + var index = indices[i]; + var offset = index.offset; + var count = index.count; + + var attribute = index.attribute; + var componentDatatype = attribute.componentDatatype; + var componentsPerAttribute = attribute.componentsPerAttribute; + + var typedArray = componentDatatype.createTypedArray(count * componentsPerAttribute); + for (var j = 0; j < count; ++j) { + typedArray.set(value, j * componentsPerAttribute); + } + + attribute.vertexBuffer.copyFromArrayView(typedArray, offset * componentDatatype.sizeInBytes); + } + } + }); + } + } + + return attributes; + }; + /** * Returns true if this object was destroyed; otherwise, false. *

From 4c67b898a5d4771f257a24da9daa54604fba0c9e Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 27 Jun 2013 21:39:39 -0400 Subject: [PATCH 257/306] Fix writing to vertex buffer by computing offset in bytes. --- Source/Scene/Primitive.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index db35f360de9d..3ddce63d7f49 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -748,7 +748,8 @@ define([ typedArray.set(value, j * componentsPerAttribute); } - attribute.vertexBuffer.copyFromArrayView(typedArray, offset * componentDatatype.sizeInBytes); + var offsetInBytes = offset * componentsPerAttribute * componentDatatype.sizeInBytes; + attribute.vertexBuffer.copyFromArrayView(typedArray, offsetInBytes); } } }); From cca4d9ef32109f138226f20da8da70db0d1a4933 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 27 Jun 2013 22:04:40 -0400 Subject: [PATCH 258/306] Modify vertex shader source if show attribute is available. Move property getter and setter function creation outside of loop. --- Apps/CesiumViewer/CesiumViewer.js | 14 +++-- Source/Scene/Primitive.js | 87 ++++++++++++++++++++----------- 2 files changed, 67 insertions(+), 34 deletions(-) diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index cc864f635c11..fd3a4f10706c 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -28,6 +28,7 @@ define([ 'Core/WallGeometry', 'Core/VertexFormat', 'Core/ColorGeometryInstanceAttribute', + 'Core/ShowGeometryInstanceAttribute', 'Scene/Primitive', 'Scene/MaterialAppearance', 'Scene/PerInstanceColorAppearance', @@ -71,6 +72,7 @@ define([ WallGeometry, VertexFormat, ColorGeometryInstanceAttribute, + ShowGeometryInstanceAttribute, Primitive, MaterialAppearance, PerInstanceColorAppearance, @@ -212,7 +214,8 @@ define([ }), id : 'geometry', attributes : { - color : new ColorGeometryInstanceAttribute(Color.CORNFLOWERBLUE) + color : new ColorGeometryInstanceAttribute(Color.CORNFLOWERBLUE), + show : new ShowGeometryInstanceAttribute(true) } }); var geometry2 = new GeometryInstance({ @@ -225,7 +228,8 @@ define([ ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-95.59777, 40.03883))), new Cartesian3(0.0, 0.0, 500000.0)), id : 'geometry2', attributes : { - color : new ColorGeometryInstanceAttribute(Color.AQUAMARINE) + color : new ColorGeometryInstanceAttribute(Color.AQUAMARINE), + show : new ShowGeometryInstanceAttribute(true) } }); //geometry2.color.alpha = 0.5; // TODO @@ -238,7 +242,8 @@ define([ ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-75.59777, 40.03883))), new Cartesian3(0.0, 0.0, 3000000.0)), id : 'geometry3', attributes : { - color : new ColorGeometryInstanceAttribute(Color.BLANCHEDALMOND) + color : new ColorGeometryInstanceAttribute(Color.BLANCHEDALMOND), + show : new ShowGeometryInstanceAttribute(true) } }); var geometry4 = new GeometryInstance({ @@ -253,7 +258,8 @@ define([ }), id : 'geometry4', attributes : { - color : new ColorGeometryInstanceAttribute(new Color(1.0, 1.0, 0.0, 0.5)) + color : new ColorGeometryInstanceAttribute(new Color(1.0, 1.0, 0.0, 0.5)), + show : new ShowGeometryInstanceAttribute(true) } }); var primitive = new Primitive({ diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index 3ddce63d7f49..9362aac8b07d 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -536,6 +536,22 @@ define([ return renamedVS + '\n' + pickMain; } + function appendShow(primitive, vertexShaderSource) { + if (typeof primitive._attributeIndices.show === 'undefined') { + return vertexShaderSource; + } + + var glPositionIndex = vertexShaderSource.indexOf('gl_Position'); + var semicolonIndex = vertexShaderSource.indexOf(';', glPositionIndex); + + var source = + 'attribute float show;\n' + + vertexShaderSource.substring(0, semicolonIndex) + + ' * show' + + vertexShaderSource.substring(semicolonIndex); + return source; + } + function validateShaderMatching(shaderProgram, attributeIndices) { // For a VAO and shader program to be compatible, the VAO must have // all active attribute in the shader program. The VAO may have @@ -605,8 +621,7 @@ define([ for (i = 0; i < length; ++i) { va.push(context.createVertexArrayFromGeometry({ geometry : geometries[i], - attributeIndices : this._attributeIndices//, - //bufferUsage : BufferUsage.STATIC_DRAW + attributeIndices : this._attributeIndices })); } @@ -658,6 +673,7 @@ define([ if (createSP) { var shaderCache = context.getShaderCache(); var vs = createColumbusViewShader(this, appearance.vertexShaderSource); + vs = appendShow(this, vs); var fs = appearance.getFragmentShaderSource(); this._sp = shaderCache.replaceShaderProgram(this._sp, vs, fs, this._attributeIndices); @@ -713,6 +729,43 @@ define([ commandList.push(this._commandLists); }; + function createGetFunction(name, perInstanceAttributes) { + return function() { + return perInstanceAttributes[name][0].value; + }; + } + + function createSetFunction(name, perInstanceAttributes) { + return function (value) { + if (typeof value === 'undefined' || typeof value.length === 'undefined' || value.length < 1 || value.length > 4) { + throw new DeveloperError('value must be and array with length between 1 and 4.'); + } + + var indices = perInstanceAttributes[name]; + var length = indices.length; + for (var i = 0; i < length; ++i) { + var index = indices[i]; + var offset = index.offset; + var count = index.count; + + var attribute = index.attribute; + var componentDatatype = attribute.componentDatatype; + var componentsPerAttribute = attribute.componentsPerAttribute; + + var typedArray = componentDatatype.createTypedArray(count * componentsPerAttribute); + for (var j = 0; j < count; ++j) { + typedArray.set(value, j * componentsPerAttribute); + } + + var offsetInBytes = offset * componentsPerAttribute * componentDatatype.sizeInBytes; + attribute.vertexBuffer.copyFromArrayView(typedArray, offsetInBytes); + } + }; + } + + /** + * DOC_TBA + */ Primitive.prototype.getGeometryInstanceAttributes = function(id) { if (typeof id === 'undefined') { throw new DeveloperError('id is required'); @@ -724,34 +777,8 @@ define([ for (var name in perInstanceAttributes) { if (perInstanceAttributes.hasOwnProperty(name)) { Object.defineProperty(attributes, name, { - get : function () { - return perInstanceAttributes[name][0].value; - }, - set : function (value) { - if (typeof value === 'undefined' || typeof value.length === 'undefined' || value.length < 1 || value.length > 4) { - throw new DeveloperError('value must be and array with length between 1 and 4.'); - } - - var indices = perInstanceAttributes[name]; - var length = indices.length; - for (var i = 0; i < length; ++i) { - var index = indices[i]; - var offset = index.offset; - var count = index.count; - - var attribute = index.attribute; - var componentDatatype = attribute.componentDatatype; - var componentsPerAttribute = attribute.componentsPerAttribute; - - var typedArray = componentDatatype.createTypedArray(count * componentsPerAttribute); - for (var j = 0; j < count; ++j) { - typedArray.set(value, j * componentsPerAttribute); - } - - var offsetInBytes = offset * componentsPerAttribute * componentDatatype.sizeInBytes; - attribute.vertexBuffer.copyFromArrayView(typedArray, offsetInBytes); - } - } + get : createGetFunction(name, perInstanceAttributes), + set : createSetFunction(name, perInstanceAttributes) }); } } From 1e7b5c361f46ac95eac94ff072e2e9056a96cdb7 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Fri, 28 Jun 2013 06:29:15 -0400 Subject: [PATCH 259/306] Fix JSHint warnings --- Apps/Sandcastle/gallery/Geometry and Appearances.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Apps/Sandcastle/gallery/Geometry and Appearances.html b/Apps/Sandcastle/gallery/Geometry and Appearances.html index bb059e1ac828..0b2f4433979d 100644 --- a/Apps/Sandcastle/gallery/Geometry and Appearances.html +++ b/Apps/Sandcastle/gallery/Geometry and Appearances.html @@ -86,7 +86,7 @@ semiMajorAxis : 500000.0, bearing : Cesium.Math.toRadians(30.0), vertexFormat : Cesium.EllipsoidSurfaceAppearance.VERTEX_FORMAT - }), + }) }); var circleInstance = new Cesium.GeometryInstance({ @@ -94,7 +94,7 @@ center : ellipsoid.cartographicToCartesian(Cesium.Cartographic.fromDegrees(-72.0, 35.0)), radius : 200000.0, vertexFormat : Cesium.EllipsoidSurfaceAppearance.VERTEX_FORMAT - }), + }) }); primitives.add(new Cesium.Primitive({ @@ -181,12 +181,12 @@ instances = []; - for (var i = 0; i < 40; i += 2) { + for (i = 0; i < 40; i += 2) { instances.push(new Cesium.GeometryInstance({ geometry : new Cesium.SimplePolylineGeometry({ positions : ellipsoid.cartographicArrayToCartesianArray([ Cesium.Cartographic.fromDegrees(-100.0 + i, 48.0), - Cesium.Cartographic.fromDegrees(-102.0 + i, 48.0), + Cesium.Cartographic.fromDegrees(-102.0 + i, 48.0) ]) }), color : new Cesium.Color(Math.random(), Math.random(), Math.random(), 1.0) From 8d1607d5aeaf22c937e272b1b180c07349ecdeda Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Fri, 28 Jun 2013 06:30:01 -0400 Subject: [PATCH 260/306] Fix JSHint warning --- Source/Core/GeometryPipeline.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Core/GeometryPipeline.js b/Source/Core/GeometryPipeline.js index c224795258ca..fc62f6c0edb5 100644 --- a/Source/Core/GeometryPipeline.js +++ b/Source/Core/GeometryPipeline.js @@ -22,7 +22,7 @@ define([ './BoundingSphere', './Geometry', './GeometryAttribute', - './RuntimeError', + './RuntimeError' ], function( barycentricCoordinates, defaultValue, From cbab302e7acacce599f34a6e93cadfe0f15e7669 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Fri, 28 Jun 2013 06:45:37 -0400 Subject: [PATCH 261/306] Update Sandcastle example to use per-instance attributes --- .../gallery/Geometry and Appearances.html | 20 ++++++++++++++----- Source/Core/ColorGeometryInstanceAttribute.js | 6 +++--- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/Apps/Sandcastle/gallery/Geometry and Appearances.html b/Apps/Sandcastle/gallery/Geometry and Appearances.html index bb059e1ac828..512adb108251 100644 --- a/Apps/Sandcastle/gallery/Geometry and Appearances.html +++ b/Apps/Sandcastle/gallery/Geometry and Appearances.html @@ -121,7 +121,9 @@ height : height, vertexFormat : Cesium.PerInstanceColorAppearance.VERTEX_FORMAT }), - color : new Cesium.Color(Math.random(), Math.random(), Math.random(), 0.5) + attributes : { + color : new Cesium.ColorGeometryInstanceAttribute(new Cesium.Color(Math.random(), Math.random(), Math.random(), 0.5)) + } })); instances.push(new Cesium.GeometryInstance({ @@ -130,7 +132,9 @@ height : height, vertexFormat : Cesium.PerInstanceColorAppearance.VERTEX_FORMAT }), - color : new Cesium.Color(Math.random(), Math.random(), Math.random(), 0.5) + attributes : { + color : new Cesium.ColorGeometryInstanceAttribute(new Cesium.Color(Math.random(), Math.random(), Math.random(), 0.5)) + } })); } @@ -156,14 +160,18 @@ geometry : boxGeometry, modelMatrix : Cesium.Matrix4.multiplyByUniformScale(Cesium.Matrix4.multiplyByTranslation(Cesium.Transforms.eastNorthUpToFixedFrame( ellipsoid.cartographicToCartesian(Cesium.Cartographic.fromDegrees(-105.0, 45.0))), new Cesium.Cartesian3(0.0, 0.0, height)), 90000.0), - color : new Cesium.Color(Math.random(), Math.random(), Math.random(), 1.0) + attributes : { + color : new Cesium.ColorGeometryInstanceAttribute(new Cesium.Color(Math.random(), Math.random(), Math.random(), 1.0)) + } })); instances.push(new Cesium.GeometryInstance({ geometry : ellipsoidGeometry, modelMatrix : Cesium.Matrix4.multiplyByUniformScale(Cesium.Matrix4.multiplyByTranslation(Cesium.Transforms.eastNorthUpToFixedFrame( ellipsoid.cartographicToCartesian(Cesium.Cartographic.fromDegrees(-102.0, 45.0))), new Cesium.Cartesian3(0.0, 0.0, height)), 90000.0), - color : new Cesium.Color(Math.random(), Math.random(), Math.random(), 1.0) + attributes : { + color : new Cesium.ColorGeometryInstanceAttribute(new Cesium.Color(Math.random(), Math.random(), Math.random(), 1.0)) + } })); } @@ -189,7 +197,9 @@ Cesium.Cartographic.fromDegrees(-102.0 + i, 48.0), ]) }), - color : new Cesium.Color(Math.random(), Math.random(), Math.random(), 1.0) + attributes : { + color : new Cesium.ColorGeometryInstanceAttribute(new Cesium.Color(Math.random(), Math.random(), Math.random(), 1.0)) + } })); } diff --git a/Source/Core/ColorGeometryInstanceAttribute.js b/Source/Core/ColorGeometryInstanceAttribute.js index 12d1aba7a989..66ab41d5e47f 100644 --- a/Source/Core/ColorGeometryInstanceAttribute.js +++ b/Source/Core/ColorGeometryInstanceAttribute.js @@ -22,11 +22,11 @@ define([ * @example * var instance = new GeometryInstance({ * geometry : new BoxGeometry({ - * vertexFormat : VertexFormat.POSITION_AND_NORMAL, - * dimensions : new Cartesian3(1000000.0, 1000000.0, 500000.0) + * dimensions : new Cartesian3(1000000.0, 1000000.0, 500000.0), + * vertexFormat : Cesium.PerInstanceColorAppearance.VERTEX_FORMAT * }), * modelMatrix : Matrix4.multiplyByTranslation(Transforms.eastNorthUpToFixedFrame( - * ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-75.59777, 40.03883))), new Cartesian3(0.0, 0.0, 1000000.0)), + * ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-75, 40))), new Cartesian3(0.0, 0.0, 1000000.0)), * id : 'box', * attributes : { * color : new ColorGeometryInstanceAttribute(Color.AQUA) From 80434316efbbf28d5bc1769b0e071f37cc1c7504 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Fri, 28 Jun 2013 07:30:00 -0400 Subject: [PATCH 262/306] Minor doc updates --- Source/Core/ColorGeometryInstanceAttribute.js | 19 ++++--- Source/Core/GeometryInstance.js | 32 ++++++------ Source/Core/GeometryInstanceAttribute.js | 52 +++++++++---------- Source/Core/ShowGeometryInstanceAttribute.js | 20 +++---- Source/Scene/Primitive.js | 10 ++-- 5 files changed, 67 insertions(+), 66 deletions(-) diff --git a/Source/Core/ColorGeometryInstanceAttribute.js b/Source/Core/ColorGeometryInstanceAttribute.js index 66ab41d5e47f..8cd5e16086ec 100644 --- a/Source/Core/ColorGeometryInstanceAttribute.js +++ b/Source/Core/ColorGeometryInstanceAttribute.js @@ -21,16 +21,15 @@ define([ * * @example * var instance = new GeometryInstance({ - * geometry : new BoxGeometry({ - * dimensions : new Cartesian3(1000000.0, 1000000.0, 500000.0), - * vertexFormat : Cesium.PerInstanceColorAppearance.VERTEX_FORMAT - * }), - * modelMatrix : Matrix4.multiplyByTranslation(Transforms.eastNorthUpToFixedFrame( - * ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-75, 40))), new Cartesian3(0.0, 0.0, 1000000.0)), - * id : 'box', - * attributes : { - * color : new ColorGeometryInstanceAttribute(Color.AQUA) - * } + * geometry : new BoxGeometry({ + * dimensions : new Cartesian3(1000000.0, 1000000.0, 500000.0) + * }), + * modelMatrix : Matrix4.multiplyByTranslation(Transforms.eastNorthUpToFixedFrame( + * ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-0.0, 0.0))), new Cartesian3(0.0, 0.0, 1000000.0)), + * id : 'box', + * attributes : { + * color : new ColorGeometryInstanceAttribute(Color.AQUA) + * } * }); * * @see GeometryInstance diff --git a/Source/Core/GeometryInstance.js b/Source/Core/GeometryInstance.js index db40a2554a7c..67a9eb74bc81 100644 --- a/Source/Core/GeometryInstance.js +++ b/Source/Core/GeometryInstance.js @@ -30,26 +30,26 @@ define([ * // One instance positions the box on the bottom and colored aqua. * // The other instance positions the box on the top and color white. * var geometry = new BoxGeometry({ - * vertexFormat : VertexFormat.POSITION_AND_NORMAL, - * dimensions : new Cartesian3(1000000.0, 1000000.0, 500000.0) + * vertexFormat : VertexFormat.POSITION_AND_NORMAL, + * dimensions : new Cartesian3(1000000.0, 1000000.0, 500000.0) * }), * var instanceBottom = new GeometryInstance({ - * geometry : geometry, - * modelMatrix : Matrix4.multiplyByTranslation(Transforms.eastNorthUpToFixedFrame( - * ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-75.59777, 40.03883))), new Cartesian3(0.0, 0.0, 1000000.0)), - * attributes : { - * color : new ColorGeometryInstanceAttribute(Color.AQUA) - * } - * id : 'bottom' + * geometry : geometry, + * modelMatrix : Matrix4.multiplyByTranslation(Transforms.eastNorthUpToFixedFrame( + * ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-75.59777, 40.03883))), new Cartesian3(0.0, 0.0, 1000000.0)), + * attributes : { + * color : new ColorGeometryInstanceAttribute(Color.AQUA) + * } + * id : 'bottom' * }); * var instanceTop = new GeometryInstance({ - * geometry : geometry, - * modelMatrix : Matrix4.multiplyByTranslation(Transforms.eastNorthUpToFixedFrame( - * ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-75.59777, 40.03883))), new Cartesian3(0.0, 0.0, 3000000.0)), - * attributes : { - * color : new ColorGeometryInstanceAttribute(Color.AQUA) - * } - * id : 'top' + * geometry : geometry, + * modelMatrix : Matrix4.multiplyByTranslation(Transforms.eastNorthUpToFixedFrame( + * ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-75.59777, 40.03883))), new Cartesian3(0.0, 0.0, 3000000.0)), + * attributes : { + * color : new ColorGeometryInstanceAttribute(Color.AQUA) + * } + * id : 'top' * }); * * @see Geometry diff --git a/Source/Core/GeometryInstanceAttribute.js b/Source/Core/GeometryInstanceAttribute.js index f1f968b83766..68aebe69479d 100644 --- a/Source/Core/GeometryInstanceAttribute.js +++ b/Source/Core/GeometryInstanceAttribute.js @@ -6,9 +6,7 @@ define([ "use strict"; /** - * Values and type information for per-instance geometry attributes. A {@link Geometry} - * generally contains one or more attributes. All attributes together form - * the geometry's vertices. + * Values and type information for per-instance geometry attributes. * * @alias GeometryInstanceAttribute * @constructor @@ -20,24 +18,24 @@ define([ * * @example * var instance = new GeometryInstance({ - * geometry : new BoxGeometry({ - * vertexFormat : VertexFormat.POSITION_AND_NORMAL, - * dimensions : new Cartesian3(1000000.0, 1000000.0, 500000.0) - * }), - * modelMatrix : Matrix4.multiplyByTranslation(Transforms.eastNorthUpToFixedFrame( - * ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-75.59777, 40.03883))), new Cartesian3(0.0, 0.0, 1000000.0)), - * id : 'box', - * attributes : { - * color : new GeometryInstanceAttribute({ - * componentDatatype : ComponentDatatype.UNSIGNED_BYTE, - * componentsPerAttribute : 4, - * normalize : true, - * value : [255, 255, 0 255] - * } - * } + * geometry : new BoxGeometry({ + * dimensions : new Cartesian3(1000000.0, 1000000.0, 500000.0) + * }), + * modelMatrix : Matrix4.multiplyByTranslation(Transforms.eastNorthUpToFixedFrame( + * ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-0.0, 0.0))), new Cartesian3(0.0, 0.0, 1000000.0)), + * id : 'box', + * attributes : { + * color : new GeometryInstanceAttribute({ + * componentDatatype : ComponentDatatype.UNSIGNED_BYTE, + * componentsPerAttribute : 4, + * normalize : true, + * value : [255, 255, 0 255] + * } + * } * }); * - * @see GeometryInstance + * @see ColorGeometryInstanceAttribute + * @see ShowGeometryInstanceAttribute */ var GeometryInstanceAttribute = function(options) { options = defaultValue(options, defaultValue.EMPTY_OBJECT); @@ -63,10 +61,10 @@ define([ * * @example * show : new GeometryInstanceAttribute({ - * componentDatatype : ComponentDatatype.UNSIGNED_BYTE, - * componentsPerAttribute : 1, - * normalize : true, - * value : 1.0 + * componentDatatype : ComponentDatatype.UNSIGNED_BYTE, + * componentsPerAttribute : 1, + * normalize : true, + * value : 1.0 * } */ this.componentsPerAttribute = options.componentsPerAttribute; @@ -107,10 +105,10 @@ define([ * * @example * show : new GeometryInstanceAttribute({ - * componentDatatype : ComponentDatatype.UNSIGNED_BYTE, - * componentsPerAttribute : 1, - * normalize : true, - * value : 1.0 + * componentDatatype : ComponentDatatype.UNSIGNED_BYTE, + * componentsPerAttribute : 1, + * normalize : true, + * value : 1.0 * } */ this.value = options.value; diff --git a/Source/Core/ShowGeometryInstanceAttribute.js b/Source/Core/ShowGeometryInstanceAttribute.js index 808ade401ac7..3f27ade5f85e 100644 --- a/Source/Core/ShowGeometryInstanceAttribute.js +++ b/Source/Core/ShowGeometryInstanceAttribute.js @@ -17,16 +17,16 @@ define([ * * @example * var instance = new GeometryInstance({ - * geometry : new BoxGeometry({ - * vertexFormat : VertexFormat.POSITION_AND_NORMAL, - * dimensions : new Cartesian3(1000000.0, 1000000.0, 500000.0) - * }), - * modelMatrix : Matrix4.multiplyByTranslation(Transforms.eastNorthUpToFixedFrame( - * ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-75.59777, 40.03883))), new Cartesian3(0.0, 0.0, 1000000.0)), - * id : 'box', - * attributes : { - * show : new ShowGeometryInstanceAttribute(false) - * } + * geometry : new BoxGeometry({ + * vertexFormat : VertexFormat.POSITION_AND_NORMAL, + * dimensions : new Cartesian3(1000000.0, 1000000.0, 500000.0) + * }), + * modelMatrix : Matrix4.multiplyByTranslation(Transforms.eastNorthUpToFixedFrame( + * ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-75.59777, 40.03883))), new Cartesian3(0.0, 0.0, 1000000.0)), + * id : 'box', + * attributes : { + * show : new ShowGeometryInstanceAttribute(false) + * } * }); * * @see GeometryInstance diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index 9362aac8b07d..7a335b9f8c9d 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -96,7 +96,9 @@ define([ * CesiumMath.toRadians(40.0)) * }), * id : 'object returned when this instance is picked and to get/set per-instance attributes', - * color : new Color(0.0, 1.0, 1.0, 0.5) // TODO: make attribute + * attribute : { + * color : new ColorGeometryInstanceAttribute(new Color(0.0, 1.0, 1.0, 0.5)) + * } * }); * var ellipsoidInstance = new GeometryInstance({ * geometry : new EllipsoidGeometry({ @@ -106,7 +108,9 @@ define([ * modelMatrix : Matrix4.multiplyByTranslation(Transforms.eastNorthUpToFixedFrame( * ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-95.59777, 40.03883))), new Cartesian3(0.0, 0.0, 500000.0)), * id : 'object returned when this instance is picked and to get/set per-instance attributes', - * color : new Color(1.0, 0.0, 1.0, 0.5) // TODO: make attribute + * attribute : { + * color : new ColorGeometryInstanceAttribute(new Color(1.0, 0.0, 1.0, 0.5)) + * } * }); * var primitive = new Primitive({ * geometryInstances : [extentInstance, ellipsoidInstance], @@ -364,7 +368,7 @@ define([ // Add pickColor attribute for picking individual instances addPickColorAttribute(primitive, instances, context); - // add attributes to the geometry for each per-instance geometry + // add attributes to the geometry for each per-instance attribute var perInstanceAttributeNames = getCommonPerInstanceAttributeNames(instances); addPerInstanceAttributes(primitive, instances, perInstanceAttributeNames); From 8010f934a9258dea810fe4193a7c7bef524cb16c Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Fri, 28 Jun 2013 09:14:47 -0400 Subject: [PATCH 263/306] More reference doc --- Source/Core/GeometryPipeline.js | 14 ++++- Source/Core/barycentricCoordinates.js | 22 +++++++- Source/Core/pointInsideTriangle.js | 22 +++++--- Source/Scene/ExtentPrimitive.js | 51 ++++++++++++++++--- Source/Scene/Polygon.js | 8 +-- Source/Scene/Primitive.js | 11 +++- .../Scene/createTangentSpaceDebugPrimitive.js | 2 + Source/Shaders/BuiltinFunctions.glsl | 18 ++++++- 8 files changed, 126 insertions(+), 22 deletions(-) diff --git a/Source/Core/GeometryPipeline.js b/Source/Core/GeometryPipeline.js index 1365542d2027..a5d8230ed2b6 100644 --- a/Source/Core/GeometryPipeline.js +++ b/Source/Core/GeometryPipeline.js @@ -1806,7 +1806,19 @@ define([ } /** - * DOC_TBA + * Splits the geometry's primitives, by introducing new vertices and indices,that + * intersect the International Date Line so that no primitives cross longitude + * -180/180 degrees. This is not required for 3D drawing, but is required for + * correcting drawing in 2D and Columbus view. + * + * @param {Geometry} geometry The geometry to modify, which is modified in place. + * + * @returns {Geometry} The modified geometry argument, with it's primitives split at the International Date Line. + * + * @exception {DeveloperError} geometry is required. + * + * @example + * geometry = GeometryPipeline.wrapLongitude(geometry); */ GeometryPipeline.wrapLongitude = function(geometry) { if (typeof geometry === 'undefined') { diff --git a/Source/Core/barycentricCoordinates.js b/Source/Core/barycentricCoordinates.js index cf2e564db648..472f87959db4 100644 --- a/Source/Core/barycentricCoordinates.js +++ b/Source/Core/barycentricCoordinates.js @@ -8,7 +8,27 @@ define([ "use strict"; /** - * DOC_TBA + * Computes the barycentric coordinates for a point with respect to a triangle. + * + * @exports pointInsideTriangle + * + * @param {Cartesian3} point The point to test. + * @param {Cartesian3} p0 The first point of the triangle, corresponding to the barycentric x-axis. + * @param {Cartesian3} p1 The second point of the triangle, corresponding to the barycentric y-axis. + * @param {Cartesian3} p2 The third point of the triangle, corresponding to the barycentric z-axis. + * @param {Cartesian3} [result] The object onto which to store the result. + * + * @return {Cartesian3} The modified result parameter or a new Cartesian3 instance if one was not provided. + * + * @exception {DeveloperError} point, p0, p1, and p2 are required. + * + * @example + * // Returns Cartesian3.UNIT_X + * var p = new Cartesian3(-1.0, 0.0, 0.0); + * var b = barycentricCoordinates(p, + * new Cartesian3(-1.0, 0.0, 0.0), + * new Cartesian3( 1.0, 0.0, 0.0), + * new Cartesian3( 0.0, 1.0, 1.0)); */ var barycentricCoordinates = function(point, p0, p1, p2, result) { if (typeof point === 'undefined' || typeof p0 === 'undefined' || typeof p1 === 'undefined' || typeof p2 === 'undefined') { diff --git a/Source/Core/pointInsideTriangle.js b/Source/Core/pointInsideTriangle.js index 42a116454745..e277a1150015 100644 --- a/Source/Core/pointInsideTriangle.js +++ b/Source/Core/pointInsideTriangle.js @@ -12,16 +12,26 @@ define([ var coords = new Cartesian3(); /** - * DOC_TBA - * - * @param point - * @param p0 - * @param p1 - * @param p2 + * Determines if a 2D point is inside a triangle. * * @exports pointInsideTriangle * + * @param {Cartesian2} point The point to test. + * @param {Cartesian2} p0 The first point of the triangle. + * @param {Cartesian2} p1 The second point of the triangle. + * @param {Cartesian2} p2 The third point of the triangle. + * + * @return {Boolean} true if the point is inside the triangle; otherwise, false. + * * @exception {DeveloperError} point, p0, p1, and p2 are required. + * + * @example + * // Returns true + * var p = new Cartesian2(0.25, 0.25); + * var b = pointInsideTriangle(p, + * new Cartesian2(0.0, 0.0), + * new Cartesian2(1.0, 0.0), + * new Cartesian2(0.0, 1.0)); */ var pointInsideTriangle = function(point, p0, p1, p2) { barycentricCoordinates(point, p0, p1, p2, coords); diff --git a/Source/Scene/ExtentPrimitive.js b/Source/Scene/ExtentPrimitive.js index c78c48d2f0f5..459981a26b9f 100644 --- a/Source/Scene/ExtentPrimitive.js +++ b/Source/Scene/ExtentPrimitive.js @@ -28,40 +28,77 @@ define([ "use strict"; /** - * DOC_TBA + * A renderable rectangular extent. * * @alias ExtentPrimitive * @constructor + * + * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid that the extent is drawn on. + * @param {Extent} [extent=undefined] The extent, which defines the rectangular region to draw. + * @param {Number} [granularity=CesiumMath.toRadians(1.0)] The distance, in radians, between each latitude and longitude in the underlying geometry. + * @param {Number} [height=0.0] The height, in meters, that the extent is raised above the {@link ExtentPrimitive#ellipsoid}. + * @param {Number} [rotation=0.0] The angle relative, in radians, to north that the extent is rotate. Positive angles rotate counter-clockwise. + * @param {Boolean} [show=true] Determines if this primitive will be shown. + * @param {Material} [material=undefined] The surface appearance of the primitive. + * + * @example + * var extentPrimitive = new ExtentPrimitive({ + * extent : Extent.fromDegrees(0.0, 20.0, 10.0, 30.0) + * }); + * primitives.add(extentPrimitive); */ var ExtentPrimitive = function(options) { options = defaultValue(options, defaultValue.EMPTY_OBJECT); /** - * DOC_TBA + * The ellipsoid that the extent is drawn on. + * + * @type Ellipsoid + * + * @default Ellipsoid.WGS84 */ this.ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84); this._ellipsoid = undefined; /** - * DOC_TBA + * The extent, which defines the rectangular region to draw. + * + * @type Extent + * + * @default undefined */ this.extent = Extent.clone(options.extent); this._extent = undefined; /** - * DOC_TBA + * The distance, in radians, between each latitude and longitude in the underlying geometry. + * A lower granularity fits the curvature of the {@link ExtentPrimitive#ellipsoid} better, + * but uses more triangles. + * + * @type Number + * + * @default CesiumMath.toRadians(1.0) */ this.granularity = defaultValue(options.granularity, CesiumMath.toRadians(1.0)); this._granularity = undefined; /** - * DOC_TBA + * The height, in meters, that the extent is raised above the {@link ExtentPrimitive#ellipsoid}. + * + * @type Number + * + * @default 0.0 */ this.height = defaultValue(options.height, 0.0); this._height = undefined; /** - * DOC_TBA + * The angle relative, in radians, to north that the extent is rotate. + * Positive angles rotate counter-clockwise. + * + * @type Number + * + * @default 0.0 */ this.rotation = defaultValue(options.rotation, 0.0); this._rotation = undefined; @@ -70,6 +107,8 @@ define([ * Determines if this primitive will be shown. * * @type Boolean + * + * @default true */ this.show = defaultValue(options.show, true); diff --git a/Source/Scene/Polygon.js b/Source/Scene/Polygon.js index 68b82327ff95..b3e3d0c7b17a 100644 --- a/Source/Scene/Polygon.js +++ b/Source/Scene/Polygon.js @@ -207,10 +207,6 @@ define([ this._createPrimitive = true; }; - function defined(value) { - return typeof value !== 'undefined'; - } - /** * @private */ @@ -231,7 +227,7 @@ define([ return; } - if (!this._createPrimitive && !defined(this._primitive)) { + if (!this._createPrimitive && (typeof this._primitive === 'undefined')) { // No positions/hierarchy to draw return; } @@ -250,7 +246,7 @@ define([ this._primitive = this._primitive && this._primitive.destroy(); - if (!defined(this._positions) && !defined(this._polygonHierarchy)) { + if ((typeof this._positions === 'undefined') && (typeof this._polygonHierarchy === 'undefined')) { return; } diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index b440e30fb433..7aeec8436c19 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -133,11 +133,20 @@ define([ * @type Array * * @default undefined + * + * @readonly */ this.geometryInstances = options.geometryInstances; /** - * DOC_TBA + * The {@link Appearance} used to shade this primitive. Each geometry + * instance is shaded with the same appearance. Some appearances, like + * {@link PerInstanceColorAppearance} allow giving each instance unique + * properties. + * + * @type Appearance + * + * @default undefined */ this.appearance = options.appearance; this._appearance = undefined; diff --git a/Source/Scene/createTangentSpaceDebugPrimitive.js b/Source/Scene/createTangentSpaceDebugPrimitive.js index a8a8fb2a0718..b20fe361b827 100644 --- a/Source/Scene/createTangentSpaceDebugPrimitive.js +++ b/Source/Scene/createTangentSpaceDebugPrimitive.js @@ -21,6 +21,8 @@ define([ * is red; binormal is green; and tangent is blue. If an attribute is not * present, it is not drawn. * + * @exports createTangentSpaceDebugPrimitive + * * @param {Geometry} geometry The Geometry instance with the attribute. * @param {Number} [length=10000.0] The length of each line segment in meters. This can be negative to point the vector in the opposite direction. * @param {Matrix4} [options.modelMatrix=Matrix4.IDENTITY] The model matrix that transforms to transform the geometry from model to world coordinates. diff --git a/Source/Shaders/BuiltinFunctions.glsl b/Source/Shaders/BuiltinFunctions.glsl index 2f8f1689eaca..0bff0b47c696 100644 --- a/Source/Shaders/BuiltinFunctions.glsl +++ b/Source/Shaders/BuiltinFunctions.glsl @@ -766,10 +766,25 @@ vec4 czm_columbusViewMorph(vec4 position2D, vec4 position3D, float time) } /** - * DOC_TBA + * Returns a position in model coordinates relative to eye taking into + * account the current scene mode: 3D, 2D, or Columbus view. + *

+ * This uses standard position attributes, position3DHigh, + * position3DLow, position2DHigh, and position2DLow, + * and should be used when writing a vertex shader for an {@link Appearance}. + *

* * @name czm_computePosition * @glslFunction + * + * @returns {vec4} The position relative to eye. + * + * @example + * vec4 p = czm_computePosition(); + * v_positionEC = (czm_modelViewRelativeToEye * p).xyz; + * gl_Position = czm_modelViewProjectionRelativeToEye * p; + * + * @see czm_translateRelativeToEye */ vec4 czm_computePosition(); @@ -1086,6 +1101,7 @@ float czm_latitudeToWebMercatorFraction(float latitude, float southMercatorYLow, * * @see czm_modelViewRelativeToEye * @see czm_modelViewProjectionRelativeToEye + * @see czm_computePosition * @see EncodedCartesian3 */ vec4 czm_translateRelativeToEye(vec3 high, vec3 low) From ccfdff9fd3c67f8f48b9887f4659ca72560ae37f Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Fri, 28 Jun 2013 11:08:11 -0400 Subject: [PATCH 264/306] Finish Sandcastle example --- .../gallery/Geometry and Appearances.html | 26 +++++++++++++++++-- Source/Core/VertexFormat.js | 7 +++-- Source/Scene/MaterialAppearance.js | 4 +-- 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/Apps/Sandcastle/gallery/Geometry and Appearances.html b/Apps/Sandcastle/gallery/Geometry and Appearances.html index 0b2f4433979d..f22f35cd40cc 100644 --- a/Apps/Sandcastle/gallery/Geometry and Appearances.html +++ b/Apps/Sandcastle/gallery/Geometry and Appearances.html @@ -145,7 +145,8 @@ vertexFormat : Cesium.PerInstanceColorAppearance.VERTEX_FORMAT }); var ellipsoidGeometry = new Cesium.EllipsoidGeometry({ - vertexFormat : Cesium.PerInstanceColorAppearance.VERTEX_FORMAT + vertexFormat : Cesium.PerInstanceColorAppearance.VERTEX_FORMAT, + ellipsoid : new Cesium.Ellipsoid(0.5, 0.5, 1.0) }); instances = []; @@ -206,7 +207,28 @@ }) })); - // TODO: wall + // Create a single wall + var wallInstance = new Cesium.GeometryInstance({ + geometry : new Cesium.WallGeometry({ + positions : ellipsoid.cartographicArrayToCartesianArray([ + Cesium.Cartographic.fromDegrees(-100.0, 42.0, 100000.0), + Cesium.Cartographic.fromDegrees(-95.0, 42.0, 100000.0), + Cesium.Cartographic.fromDegrees(-95.0, 45.0, 100000.0), + Cesium.Cartographic.fromDegrees(-100.0, 45.0, 100000.0), + Cesium.Cartographic.fromDegrees(-100.0, 42.0, 100000.0) + ]) + }) + }); + var wallMaterial = Cesium.Material.fromType(scene.getContext(), 'Checkerboard'); + var wallPrimitive = new Cesium.Primitive({ + geometryInstances : wallInstance, + appearance : new Cesium.MaterialAppearance({ + material : wallMaterial, + faceForward : true + }) + }); + wallMaterial.uniforms.repeat = new Cesium.Cartesian2(20.0, 6.0); + scene.getPrimitives().add(wallPrimitive); Sandcastle.finishedLoading(); }); diff --git a/Source/Core/VertexFormat.js b/Source/Core/VertexFormat.js index 076f4a16fd09..6cf0197673ac 100644 --- a/Source/Core/VertexFormat.js +++ b/Source/Core/VertexFormat.js @@ -166,14 +166,17 @@ define([ })); /** - * An immutable vertex format with position and normal attributes. + * An immutable vertex format with position, normal, and st attributes. + * This is compatible with most appearances and materials; however + * normal and st attributes are not always required. When this is + * known in advance, another VertexFormat should be used. * * @memberof VertexFormat * * @see VertexFormat#position * @see VertexFormat#normal */ - VertexFormat.DEFAULT = VertexFormat.POSITION_AND_NORMAL; + VertexFormat.DEFAULT = VertexFormat.POSITION_NORMAL_AND_ST; return VertexFormat; }); \ No newline at end of file diff --git a/Source/Scene/MaterialAppearance.js b/Source/Scene/MaterialAppearance.js index b42a9056addd..e00152017dfe 100644 --- a/Source/Scene/MaterialAppearance.js +++ b/Source/Scene/MaterialAppearance.js @@ -36,7 +36,7 @@ define([ * @param {Boolean} [options.faceForward=false] When true, the fragment shader flips the surface normal as needed to ensure that the normal faces the viewer to avoid dark spots. This is useful when both sides of a geometry should be shaded like {@link WallGeometry}. * @param {Boolean} [options.translucent=true] When true, the geometry is expected to appear translucent so {@link MaterialAppearance#renderState} has alpha blending enabled. * @param {Boolean} [options.closed=false] When true, the geometry is expected to be closed so {@link MaterialAppearance#renderState} has backface culling enabled. - * @param {MaterialAppearance.MaterialSupport} [options.materialSupport=MaterialAppearance.MaterialSupport.BASIC] The type of materials that will be supported. + * @param {MaterialAppearance.MaterialSupport} [options.materialSupport=MaterialAppearance.MaterialSupport.TEXTURED] The type of materials that will be supported. * @param {Material} [options.material=Material.ColorType] The material used to determine the fragment color. * @param {String} [options.vertexShaderSource=undefined] Optional GLSL vertex shader source to override the default vertex shader. * @param {String} [options.fragmentShaderSource=undefined] Optional GLSL fragment shader source to override the default fragment shader. @@ -63,7 +63,7 @@ define([ var translucent = defaultValue(options.translucent, true); var closed = defaultValue(options.closed, false); - var materialSupport = defaultValue(options.materialSupport, MaterialAppearance.MaterialSupport.BASIC); + var materialSupport = defaultValue(options.materialSupport, MaterialAppearance.MaterialSupport.TEXTURED); /** * The material used to determine the fragment color. Unlike other {@link MaterialAppearance} From e55e3592af46a4e5afea548716d97143a5b87915 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Fri, 28 Jun 2013 11:37:50 -0400 Subject: [PATCH 265/306] Polygon doc --- Source/Scene/ExtentPrimitive.js | 4 +- Source/Scene/Polygon.js | 70 ++++++++++++++++++++++----------- 2 files changed, 50 insertions(+), 24 deletions(-) diff --git a/Source/Scene/ExtentPrimitive.js b/Source/Scene/ExtentPrimitive.js index 459981a26b9f..e1216b1ed4d8 100644 --- a/Source/Scene/ExtentPrimitive.js +++ b/Source/Scene/ExtentPrimitive.js @@ -37,7 +37,7 @@ define([ * @param {Extent} [extent=undefined] The extent, which defines the rectangular region to draw. * @param {Number} [granularity=CesiumMath.toRadians(1.0)] The distance, in radians, between each latitude and longitude in the underlying geometry. * @param {Number} [height=0.0] The height, in meters, that the extent is raised above the {@link ExtentPrimitive#ellipsoid}. - * @param {Number} [rotation=0.0] The angle relative, in radians, to north that the extent is rotate. Positive angles rotate counter-clockwise. + * @param {Number} [rotation=0.0] The angle, in radians, relative to north that the extent is rotated. Positive angles rotate counter-clockwise. * @param {Boolean} [show=true] Determines if this primitive will be shown. * @param {Material} [material=undefined] The surface appearance of the primitive. * @@ -93,7 +93,7 @@ define([ this._height = undefined; /** - * The angle relative, in radians, to north that the extent is rotate. + * The angle, in radians, relative to north that the extent is rotated. * Positive angles rotate counter-clockwise. * * @type Number diff --git a/Source/Scene/Polygon.js b/Source/Scene/Polygon.js index b3e3d0c7b17a..d51639909ba0 100644 --- a/Source/Scene/Polygon.js +++ b/Source/Scene/Polygon.js @@ -30,7 +30,7 @@ define([ "use strict"; /** - * DOC_TBA + * A renderable polygon or hierarchy of polygons. * * @alias Polygon * @constructor @@ -55,33 +55,54 @@ define([ options = defaultValue(options, defaultValue.EMPTY_OBJECT); /** - * DOC_TBA + * The ellipsoid that the polygon is drawn on. + * + * @type Ellipsoid + * + * @default Ellipsoid.WGS84 */ this.ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84); this._ellipsoid = undefined; /** - * DOC_TBA + * The distance, in radians, between each latitude and longitude in the underlying geometry. + * A lower granularity fits the curvature of the {@link Polygon#ellipsoid} better, + * but uses more triangles. + * + * @type Number + * + * @default CesiumMath.toRadians(1.0) */ this.granularity = defaultValue(options.granularity, CesiumMath.toRadians(1.0)); this._granularity = undefined; /** - * DOC_TBA + * The height, in meters, that the polygon is raised above the {@link Polygon#ellipsoid}. + * + * @type Number + * + * @default 0.0 */ this.height = defaultValue(options.height, 0.0); this._height = undefined; /** - * DOC_TBA + * The angle, in radians, relative to north that the polygon's texture is rotated. + * Positive angles rotate counter-clockwise. + * + * @type Number + * + * @default 0.0 */ - this.textureRotationAngle = options.textureRotationAngle; + this.textureRotationAngle = defaultValue(options.textureRotationAngle, 0.0); this._textureRotationAngle = undefined; /** * Determines if this primitive will be shown. * * @type Boolean + * + * @default true */ this.show = defaultValue(options.show, true); @@ -116,7 +137,8 @@ define([ }; /** - * DOC_TBA + * Returns the positions that define the boundary of the polygon. If {@link Polygon#configureFromPolygonHierarchy} + * was used, this returns undefined. * * @memberof Polygon * @@ -129,7 +151,7 @@ define([ }; /** - * DOC_TBA + * Sets positions that define the boundary of the polygon. * * @memberof Polygon * @@ -186,20 +208,24 @@ define([ *
* * - * @exception {DeveloperError} At least three positions are required. + * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called. * * @example * // A triangle within a triangle * var hierarchy = { - * positions : [new Cartesian3(-634066.5629045101,-4608738.034138676,4348640.761750969), - * new Cartesian3(-1321523.0597310204,-5108871.981065817,3570395.2500986718), - * new Cartesian3(46839.74837473363,-5303481.972379478,3530933.5841716)], - * holes : [{ - * positions :[new Cartesian3(-646079.44483647,-4811233.11175887,4123187.2266941597), - * new Cartesian3(-1024015.4454943262,-5072141.413164587,3716492.6173834214), - * new Cartesian3(-234678.22583880965,-5189078.820849883,3688809.059214336)] - * }] - * }; + * positions : [ + * new Cartesian3(-634066.5629045101, -4608738.034138676, 4348640.761750969), + * new Cartesian3(-1321523.0597310204, -5108871.981065817, 3570395.2500986718), + * new Cartesian3(46839.74837473363, -5303481.972379478, 3530933.5841716) + * ], + * holes : [{ + * positions :[ + * new Cartesian3(-646079.44483647, -4811233.11175887, 4123187.2266941597), + * new Cartesian3(-1024015.4454943262, -5072141.413164587, 3716492.6173834214), + * new Cartesian3(-234678.22583880965, -5189078.820849883, 3688809.059214336) + * ] + * }] + * }; */ Polygon.prototype.configureFromPolygonHierarchy = function(hierarchy) { this._positions = undefined; @@ -281,11 +307,11 @@ define([ * If this object was destroyed, it should not be used; calling any function other than * isDestroyed will result in a {@link DeveloperError} exception. * - * @memberof Extent + * @memberof Polygon * * @return {Boolean} true if this object was destroyed; otherwise, false. * - * @see Extent#destroy + * @see Polygon#destroy */ Polygon.prototype.isDestroyed = function() { return false; @@ -305,10 +331,10 @@ define([ * * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called. * - * @see Extent#isDestroyed + * @see Polygon#isDestroyed * * @example - * extent = extent && extent.destroy(); + * polygon = polygon && polygon.destroy(); */ Polygon.prototype.destroy = function() { this._primitive = this._primitive && this._primitive.destroy(); From 19020eb9f35db73280079128721a3aa951d603ea Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Fri, 28 Jun 2013 14:47:45 -0400 Subject: [PATCH 266/306] Revert changes to GeometryPipeline, Context, and VertexLayout. Add optional parameter to createVertexArrayFromGeometry for already created vertex array attributes. --- Source/Core/GeometryPipeline.js | 193 +------------------------- Source/Renderer/Context.js | 238 ++++++++++++++++++++++++++------ Source/Renderer/VertexLayout.js | 49 +++++++ Source/Scene/Primitive.js | 81 ++++++----- 4 files changed, 294 insertions(+), 267 deletions(-) create mode 100644 Source/Renderer/VertexLayout.js diff --git a/Source/Core/GeometryPipeline.js b/Source/Core/GeometryPipeline.js index dd1e03e9dc39..a5d8230ed2b6 100644 --- a/Source/Core/GeometryPipeline.js +++ b/Source/Core/GeometryPipeline.js @@ -21,8 +21,7 @@ define([ './Tipsify', './BoundingSphere', './Geometry', - './GeometryAttribute', - './RuntimeError' + './GeometryAttribute' ], function( barycentricCoordinates, defaultValue, @@ -45,8 +44,7 @@ define([ Tipsify, BoundingSphere, Geometry, - GeometryAttribute, - RuntimeError) { + GeometryAttribute) { "use strict"; /** @@ -1845,192 +1843,5 @@ define([ return geometry; }; - function computeNumberOfVertices(attribute) { - return attribute.values.length / attribute.componentsPerAttribute; - } - - function computeAttributeSizeInBytes(attribute) { - return attribute.componentDatatype.sizeInBytes * attribute.componentsPerAttribute; - } - - function createInterleavedBuffer(geometry, attributeNames) { - var j; - var name; - var attribute; - var attributes = geometry.attributes; - - // Extract attribute names. - var names = []; - if (typeof attributeNames !== 'undefined') { - var length = attributeNames.length; - for (j = 0; j < length; ++j) { - name = attributeNames[j]; - attribute = attributes[name]; - - // Attribute needs to have per-vertex values; not a constant value for all vertices. - if (typeof attribute !== 'undefined' && typeof attribute.values !== 'undefined') { - names.push(name); - - if (attribute.componentDatatype === ComponentDatatype.DOUBLE) { - attribute.componentDatatype = ComponentDatatype.FLOAT; - attribute.values = ComponentDatatype.FLOAT.createTypedArray(attribute.values); - } - } - } - } else { - for (name in attributes) { - // Attribute needs to have per-vertex values; not a constant value for all vertices. - if (attributes.hasOwnProperty(name) && typeof attributes[name].values !== 'undefined') { - attribute = attributes[name]; - names.push(name); - - if (attribute.componentDatatype === ComponentDatatype.DOUBLE) { - attribute.componentDatatype = ComponentDatatype.FLOAT; - attribute.values = ComponentDatatype.FLOAT.createTypedArray(attribute.values); - } - } - } - } - - // Validation. Compute number of vertices. - var numberOfVertices; - var namesLength = names.length; - - if (namesLength > 0) { - numberOfVertices = computeNumberOfVertices(attributes[names[0]]); - - for (j = 1; j < namesLength; ++j) { - var currentNumberOfVertices = computeNumberOfVertices(attributes[names[j]]); - - if (currentNumberOfVertices !== numberOfVertices) { - throw new RuntimeError( - 'Each attribute list must have the same number of vertices. ' + - 'Attribute ' + names[j] + ' has a different number of vertices ' + - '(' + currentNumberOfVertices.toString() + ')' + - ' than attribute ' + names[0] + - ' (' + numberOfVertices.toString() + ').'); - } - } - } - - // Sort attributes by the size of their components. From left to right, a vertex stores floats, shorts, and then bytes. - names.sort(function(left, right) { - return attributes[right].componentDatatype.sizeInBytes - attributes[left].componentDatatype.sizeInBytes; - }); - - // Compute sizes and strides. - var vertexSizeInBytes = 0; - var offsetsInBytes = {}; - - for (j = 0; j < namesLength; ++j) { - name = names[j]; - attribute = attributes[name]; - - offsetsInBytes[name] = vertexSizeInBytes; - vertexSizeInBytes += computeAttributeSizeInBytes(attribute); - } - - if (vertexSizeInBytes > 0) { - // Pad each vertex to be a multiple of the largest component datatype so each - // attribute can be addressed using typed arrays. - var maxComponentSizeInBytes = attributes[names[0]].componentDatatype.sizeInBytes; // Sorted large to small - var remainder = vertexSizeInBytes % maxComponentSizeInBytes; - if (remainder !== 0) { - vertexSizeInBytes += (maxComponentSizeInBytes - remainder); - } - - // Total vertex buffer size in bytes, including per-vertex padding. - var vertexBufferSizeInBytes = numberOfVertices * vertexSizeInBytes; - - // Create array for interleaved vertices. Each attribute has a different view (pointer) into the array. - var buffer = new ArrayBuffer(vertexBufferSizeInBytes); - var views = {}; - - for (j = 0; j < namesLength; ++j) { - name = names[j]; - var sizeInBytes = attributes[name].componentDatatype.sizeInBytes; - - views[name] = { - pointer : attributes[name].componentDatatype.createTypedArray(buffer), - index : offsetsInBytes[name] / sizeInBytes, // Offset in ComponentType - strideInComponentType : vertexSizeInBytes / sizeInBytes - }; - } - - // Copy attributes into one interleaved array. - // PERFORMANCE_IDEA: Can we optimize these loops? - for (j = 0; j < numberOfVertices; ++j) { - for ( var n = 0; n < namesLength; ++n) { - name = names[n]; - attribute = attributes[name]; - var values = attribute.values; - var view = views[name]; - var pointer = view.pointer; - - var numberOfComponents = attribute.componentsPerAttribute; - for ( var k = 0; k < numberOfComponents; ++k) { - pointer[view.index + k] = values[(j * numberOfComponents) + k]; - } - - view.index += view.strideInComponentType; - } - } - - return { - buffer : buffer, - offsetsInBytes : offsetsInBytes, - vertexSizeInBytes : vertexSizeInBytes - }; - } - - // No attributes to interleave. - return undefined; - } - - /** - * DOC_TBA - */ - GeometryPipeline.interleaveAttributes = function(geometry, attributeNames) { - if (typeof geometry === 'undefined') { - throw new DeveloperError('geometry is required.'); - } - - var interleavedAttributes = createInterleavedBuffer(geometry, attributeNames); - if (typeof interleavedAttributes !== 'undefined') { - var buffer = interleavedAttributes.buffer; - var offsetsInBytes = interleavedAttributes.offsetsInBytes; - var vertexSizeInBytes = interleavedAttributes.vertexSizeInBytes; - - var attributes = geometry.attributes; - var name; - var attribute; - - if (typeof attributeNames !== 'undefined') { - var namesLength = attributeNames.length; - for (var i = 0; i < namesLength; ++i) { - name = attributeNames[i]; - attribute = attributes[name]; - if (typeof attribute.values !== 'undefined') { - attribute.values = undefined; - attribute.interleavedValues = buffer; - attribute.offsetInBytes = offsetsInBytes[name]; - attribute.strideInBytes = vertexSizeInBytes; - } - } - } else { - for (name in attributes) { - if (attributes.hasOwnProperty(name) && typeof attributes[name].values !== 'undefined') { - attribute = attributes[name]; - attribute.values = undefined; - attribute.interleavedValues = buffer; - attribute.offsetInBytes = offsetsInBytes[name]; - attribute.strideInBytes = vertexSizeInBytes; - } - } - } - } - return geometry; - }; - return GeometryPipeline; }); diff --git a/Source/Renderer/Context.js b/Source/Renderer/Context.js index 9093a612839e..47d02e65423e 100644 --- a/Source/Renderer/Context.js +++ b/Source/Renderer/Context.js @@ -30,6 +30,7 @@ define([ './TextureWrap', './UniformState', './VertexArray', + './VertexLayout', './ClearCommand', './PassState' ], function( @@ -63,6 +64,7 @@ define([ TextureWrap, UniformState, VertexArray, + VertexLayout, ClearCommand, PassState) { "use strict"; @@ -2180,6 +2182,130 @@ define([ return pixels; }; + ////////////////////////////////////////////////////////////////////////////////////////// + + function computeNumberOfVertices(attribute) { + return attribute.values.length / attribute.componentsPerAttribute; + } + + function computeAttributeSizeInBytes(attribute) { + return attribute.componentDatatype.sizeInBytes * attribute.componentsPerAttribute; + } + + function interleaveAttributes(attributes) { + var j; + var name; + var attribute; + + // Extract attribute names. + var names = []; + for (name in attributes) { + // Attribute needs to have per-vertex values; not a constant value for all vertices. + if (attributes.hasOwnProperty(name) && typeof attributes[name].values !== 'undefined') { + names.push(name); + + if (attributes[name].componentDatatype === ComponentDatatype.DOUBLE) { + attributes[name].componentDatatype = ComponentDatatype.FLOAT; + attributes[name].values = ComponentDatatype.FLOAT.createTypedArray(attributes[name].values); + } + } + } + + // Validation. Compute number of vertices. + var numberOfVertices; + var namesLength = names.length; + + if (namesLength > 0) { + numberOfVertices = computeNumberOfVertices(attributes[names[0]]); + + for (j = 1; j < namesLength; ++j) { + var currentNumberOfVertices = computeNumberOfVertices(attributes[names[j]]); + + if (currentNumberOfVertices !== numberOfVertices) { + throw new RuntimeError( + 'Each attribute list must have the same number of vertices. ' + + 'Attribute ' + names[j] + ' has a different number of vertices ' + + '(' + currentNumberOfVertices.toString() + ')' + + ' than attribute ' + names[0] + + ' (' + numberOfVertices.toString() + ').'); + } + } + } + + // Sort attributes by the size of their components. From left to right, a vertex stores floats, shorts, and then bytes. + names.sort(function(left, right) { + return attributes[right].componentDatatype.sizeInBytes - attributes[left].componentDatatype.sizeInBytes; + }); + + // Compute sizes and strides. + var vertexSizeInBytes = 0; + var offsetsInBytes = {}; + + for (j = 0; j < namesLength; ++j) { + name = names[j]; + attribute = attributes[name]; + + offsetsInBytes[name] = vertexSizeInBytes; + vertexSizeInBytes += computeAttributeSizeInBytes(attribute); + } + + if (vertexSizeInBytes > 0) { + // Pad each vertex to be a multiple of the largest component datatype so each + // attribute can be addressed using typed arrays. + var maxComponentSizeInBytes = attributes[names[0]].componentDatatype.sizeInBytes; // Sorted large to small + var remainder = vertexSizeInBytes % maxComponentSizeInBytes; + if (remainder !== 0) { + vertexSizeInBytes += (maxComponentSizeInBytes - remainder); + } + + // Total vertex buffer size in bytes, including per-vertex padding. + var vertexBufferSizeInBytes = numberOfVertices * vertexSizeInBytes; + + // Create array for interleaved vertices. Each attribute has a different view (pointer) into the array. + var buffer = new ArrayBuffer(vertexBufferSizeInBytes); + var views = {}; + + for (j = 0; j < namesLength; ++j) { + name = names[j]; + var sizeInBytes = attributes[name].componentDatatype.sizeInBytes; + + views[name] = { + pointer : attributes[name].componentDatatype.createTypedArray(buffer), + index : offsetsInBytes[name] / sizeInBytes, // Offset in ComponentType + strideInComponentType : vertexSizeInBytes / sizeInBytes + }; + } + + // Copy attributes into one interleaved array. + // PERFORMANCE_IDEA: Can we optimize these loops? + for (j = 0; j < numberOfVertices; ++j) { + for ( var n = 0; n < namesLength; ++n) { + name = names[n]; + attribute = attributes[name]; + var values = attribute.values; + var view = views[name]; + var pointer = view.pointer; + + var numberOfComponents = attribute.componentsPerAttribute; + for ( var k = 0; k < numberOfComponents; ++k) { + pointer[view.index + k] = values[(j * numberOfComponents) + k]; + } + + view.index += view.strideInComponentType; + } + } + + return { + buffer : buffer, + offsetsInBytes : offsetsInBytes, + vertexSizeInBytes : vertexSizeInBytes + }; + } + + // No attributes to interleave. + return undefined; + } + /** * Creates a vertex array from a geometry. A geometry contains vertex attributes and optional index data * in system memory, whereas a vertex array contains vertex buffers and an optional index buffer in WebGL @@ -2192,6 +2318,7 @@ define([ *
  • geometry: The source geometry containing data used to create the vertex array.
  • *
  • attributeIndices: An object that maps geometry attribute names to vertex shader attribute indices.
  • *
  • bufferUsage: The expected usage pattern of the vertex array's buffers. On some WebGL implementations, this can significantly affect performance. See {@link BufferUsage}. Default: BufferUsage.DYNAMIC_DRAW.
  • + *
  • vertexLayout: Determines if all attributes are interleaved in a single vertex buffer or if each attribute is stored in a separate vertex buffer. Default: VertexLayout.SEPARATE.
  • * *
    * If creationArguments is not specified or the geometry contains no data, the returned vertex array is empty. @@ -2222,7 +2349,18 @@ define([ * * //////////////////////////////////////////////////////////////////////////////// * - * // Example 2. When the caller destroys the vertex array, it also destroys the + * // Example 2. Creates a vertex array with interleaved attributes in a + * // single vertex buffer. The vertex and index buffer have static draw usage. + * var va = context.createVertexArrayFromGeometry({ + * geometry : geometry, + * attributeIndices : GeometryPipeline.createAttributeIndices(geometry), + * bufferUsage : BufferUsage.STATIC_DRAW, + * vertexLayout : VertexLayout.INTERLEAVED + * }); + * + * //////////////////////////////////////////////////////////////////////////////// + * + * // Example 3. When the caller destroys the vertex array, it also destroys the * // attached vertex buffer(s) and index buffer. * va = va.destroy(); */ @@ -2231,57 +2369,77 @@ define([ var geometry = defaultValue(ca.geometry, defaultValue.EMPTY_OBJECT); var bufferUsage = defaultValue(ca.bufferUsage, BufferUsage.DYNAMIC_DRAW); + var attributeIndices = defaultValue(ca.attributeIndices, defaultValue.EMPTY_OBJECT); + var interleave = (typeof ca.vertexLayout !== 'undefined') && (ca.vertexLayout === VertexLayout.INTERLEAVED); + var createdVAAttributes = ca.vertexArrayAttributes; var name; var attribute; var vertexBuffer; - var vaAttributes = []; + var vaAttributes = (typeof createdVAAttributes !== 'undefined') ? createdVAAttributes : []; var attributes = geometry.attributes; - var interleavedBuffers = []; - - for (name in attributes) { - if (attributes.hasOwnProperty(name)) { - attribute = attributes[name]; - var componentDatatype = attribute.componentDatatype; - if (componentDatatype === ComponentDatatype.DOUBLE) { - componentDatatype = ComponentDatatype.FLOAT; - } - - vertexBuffer = undefined; - if (typeof attribute.interleavedValues !== 'undefined') { - var values = attribute.interleavedValues; - var length = interleavedBuffers.length; - for (var i = 0; i < length; ++i) { - var interleavedBuffer = interleavedBuffers[i]; - if (values === interleavedBuffer.values) { - vertexBuffer = interleavedBuffer.vertexBuffer; - break; + if (interleave) { + // Use a single vertex buffer with interleaved vertices. + var interleavedAttributes = interleaveAttributes(attributes); + if (typeof interleavedAttributes !== 'undefined') { + vertexBuffer = this.createVertexBuffer(interleavedAttributes.buffer, bufferUsage); + var offsetsInBytes = interleavedAttributes.offsetsInBytes; + var strideInBytes = interleavedAttributes.vertexSizeInBytes; + + for (name in attributes) { + if (attributes.hasOwnProperty(name)) { + attribute = attributes[name]; + + if (typeof attribute.values !== 'undefined') { + // Common case: per-vertex attributes + vaAttributes.push({ + index : attributeIndices[name], + vertexBuffer : vertexBuffer, + componentDatatype : attribute.componentDatatype, + componentsPerAttribute : attribute.componentsPerAttribute, + normalize : attribute.normalize, + offsetInBytes : offsetsInBytes[name], + strideInBytes : strideInBytes + }); + } else { + // Constant attribute for all vertices + vaAttributes.push({ + index : attributeIndices[name], + value : attribute.value, + componentDatatype : attribute.componentDatatype, + normalize : attribute.normalize + }); } } + } + } + } else { + // One vertex buffer per attribute. + for (name in attributes) { + if (attributes.hasOwnProperty(name)) { + attribute = attributes[name]; + + var componentDatatype = attribute.componentDatatype; + if (componentDatatype === ComponentDatatype.DOUBLE) { + componentDatatype = ComponentDatatype.FLOAT; + } - if (typeof vertexBuffer === 'undefined') { - vertexBuffer = this.createVertexBuffer(values, bufferUsage); - interleavedBuffers.push({ - values : values, - vertexBuffer : vertexBuffer - }); + vertexBuffer = undefined; + if (typeof attribute.values !== 'undefined') { + vertexBuffer = this.createVertexBuffer(componentDatatype.createTypedArray(attribute.values), bufferUsage); } - } else if (typeof attribute.values !== 'undefined') { - vertexBuffer = this.createVertexBuffer(componentDatatype.createTypedArray(attribute.values), bufferUsage); - } - vaAttributes.push({ - index : attributeIndices[name], - vertexBuffer : vertexBuffer, - value : attribute.value, - componentDatatype : componentDatatype, - componentsPerAttribute : attribute.componentsPerAttribute, - normalize : attribute.normalize, - offsetInBytes : defaultValue(attribute.offsetInBytes, 0), - strideInBytes : defaultValue(attribute.strideInBytes, 0) - }); + vaAttributes.push({ + index : attributeIndices[name], + vertexBuffer : vertexBuffer, + value : attribute.value, + componentDatatype : componentDatatype, + componentsPerAttribute : attribute.componentsPerAttribute, + normalize : attribute.normalize + }); + } } } diff --git a/Source/Renderer/VertexLayout.js b/Source/Renderer/VertexLayout.js new file mode 100644 index 000000000000..53930b8f4c27 --- /dev/null +++ b/Source/Renderer/VertexLayout.js @@ -0,0 +1,49 @@ +/*global define*/ +define(['../Core/Enumeration'], function(Enumeration) { + "use strict"; + + /** + * Determines if vertex attributes are interleaved in a single vertex buffer or if each attribute is stored in a separate vertex buffer. + * + * @exports VertexLayout + * + * @see Context#createVertexArrayFromGeometry + */ + var VertexLayout = { + /** + * Each attribute will be stored in a separate vertex buffer. This can be slightly slower + * than using a single interleaved vertex buffer, but it is more flexible; more easily allowing + * the sharing of vertex buffers among vertex arrays. It also requires much less initial CPU + * processing than interleaving. + * + * @constant + * @type {Enumeration} + */ + SEPARATE : new Enumeration(0, 'SEPARATE'), + /** + * Each attribute will be interleaved in a single vertex buffer. This can have a slight + * performance advantage over using a separate vertex buffer per attribute, but it requires + * extra CPU processing to initially interleave the vertex data. This is recommended for + * static data that will be rendered over several frames. + * + * @constant + * @type {Enumeration} + */ + INTERLEAVED : new Enumeration(1, 'INTERLEAVED'), + + /** + * DOC_TBA + * + * @param vertexLayout + * + * @returns {Boolean} + */ + validate : function(vertexLayout) { + return ((vertexLayout === VertexLayout.SEPARATE) || + (vertexLayout === VertexLayout.INTERLEAVED)); + } + + }; + + return VertexLayout; +}); \ No newline at end of file diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index 7455f82eb789..b2792fa97e4f 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -14,6 +14,7 @@ define([ '../Core/ComponentDatatype', '../Core/Cartesian3', '../Renderer/BufferUsage', + '../Renderer/VertexLayout', '../Renderer/CommandLists', '../Renderer/DrawCommand', '../Renderer/createPickFragmentShaderSource', @@ -33,6 +34,7 @@ define([ ComponentDatatype, Cartesian3, BufferUsage, + VertexLayout, CommandLists, DrawCommand, createPickFragmentShaderSource, @@ -301,28 +303,6 @@ define([ return attributesInAllInstances; } - function getInterleavedAttributeNames(geometry, perInstanceNames) { - var interleavedNames = []; - var attributes = geometry.attributes; - var length = perInstanceNames.length; - for (var name in attributes) { - if (attributes.hasOwnProperty(name)) { - var isPerInstanceName = false; - for (var i = 0; i < length; ++i) { - if (name === perInstanceNames[i]) { - isPerInstanceName = true; - break; - } - } - - if (!isPerInstanceName) { - interleavedNames.push(name); - } - } - } - return interleavedNames; - } - function addPerInstanceAttributes(primitive, instances, names) { var length = instances.length; for (var i = 0; i < length; ++i) { @@ -403,23 +383,44 @@ define([ GeometryPipeline.encodeAttribute(geometry, 'position', 'position3DHigh', 'position3DLow'); } - - var geometries; if (!context.getElementIndexUint()) { // Break into multiple geometries to fit within unsigned short indices if needed - geometries = GeometryPipeline.fitToUnsignedShortIndices(geometry); - } else { - // Unsigned int indices are supported. No need to break into multiple geometries. - geometries = [geometry]; + return GeometryPipeline.fitToUnsignedShortIndices(geometry); } - var interleavedNames = getInterleavedAttributeNames(geometry, perInstanceAttributeNames); - length = geometries.length; - for (i = 0; i < length; ++i) { - GeometryPipeline.interleaveAttributes(geometries[i], interleavedNames); + // Unsigned int indices are supported. No need to break into multiple geometries. + return [geometry]; + } + + function createPerInstanceVAAttributes(context, geometry, attributeIndices, names) { + var vaAttributes = []; + + var bufferUsage = BufferUsage.DYNAMIC_DRAW; + var attributes = geometry.attributes; + + var length = names.length; + for (var i = 0; i < length; ++i) { + var name = names[i]; + var attribute = attributes[name]; + + var componentDatatype = attribute.componentDatatype; + if (componentDatatype === ComponentDatatype.DOUBLE) { + componentDatatype = ComponentDatatype.FLOAT; + } + + var vertexBuffer = context.createVertexBuffer(componentDatatype.createTypedArray(attribute.values), bufferUsage); + vaAttributes.push({ + index : attributeIndices[name], + vertexBuffer : vertexBuffer, + componentDatatype : componentDatatype, + componentsPerAttribute : attribute.componentsPerAttribute, + normalize : attribute.normalize + }); + + delete attributes[name]; } - return geometries; + return vaAttributes; } function computePerInstanceAttributeIndices(instances, vertexArrays, attributeIndices) { @@ -629,12 +630,20 @@ define([ this._boundingSphere2D = BoundingSphere.projectTo2D(this._boundingSphere, projection); } + var geometry; + var perInstanceAttributeNames = getCommonPerInstanceAttributeNames(insts); + var va = []; length = geometries.length; for (i = 0; i < length; ++i) { + geometry = geometries[i]; + var vaAttributes = createPerInstanceVAAttributes(context, geometry, this._attributeIndices, perInstanceAttributeNames); va.push(context.createVertexArrayFromGeometry({ - geometry : geometries[i], - attributeIndices : this._attributeIndices + geometry : geometry, + attributeIndices : this._attributeIndices, + bufferUsage : BufferUsage.STATIC_DRAW, + vertexLayout : VertexLayout.INTERLEAVED, + vertexArrayAttributes : vaAttributes })); } @@ -642,7 +651,7 @@ define([ this._perInstanceAttributes = computePerInstanceAttributeIndices(insts, va, this._attributeIndices); for (i = 0; i < length; ++i) { - var geometry = geometries[i]; + geometry = geometries[i]; // renderState, shaderProgram, and uniformMap for commands are set below. From ad3c141ed7e618affe3df23730f71180df227069 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Fri, 28 Jun 2013 16:04:09 -0400 Subject: [PATCH 267/306] Updates to ColorGeometryInstanceAttribute based on review. --- Apps/CesiumViewer/CesiumViewer.js | 17 +++++----- .../gallery/Geometry and Appearances.html | 12 +++---- Source/Core/ColorGeometryInstanceAttribute.js | 32 ++++++++++++------- Source/Core/GeometryInstanceAttribute.js | 9 +++++- Source/Scene/Primitive.js | 4 +-- 5 files changed, 44 insertions(+), 30 deletions(-) diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index fd3a4f10706c..94c390654450 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -214,7 +214,7 @@ define([ }), id : 'geometry', attributes : { - color : new ColorGeometryInstanceAttribute(Color.CORNFLOWERBLUE), + color : ColorGeometryInstanceAttribute.fromColor(Color.CORNFLOWERBLUE), show : new ShowGeometryInstanceAttribute(true) } }); @@ -228,11 +228,10 @@ define([ ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-95.59777, 40.03883))), new Cartesian3(0.0, 0.0, 500000.0)), id : 'geometry2', attributes : { - color : new ColorGeometryInstanceAttribute(Color.AQUAMARINE), + color : ColorGeometryInstanceAttribute.fromColor(Color.AQUAMARINE), show : new ShowGeometryInstanceAttribute(true) } }); - //geometry2.color.alpha = 0.5; // TODO var geometry3 = new GeometryInstance({ geometry : new BoxGeometry({ vertexFormat : PerInstanceColorAppearance.VERTEX_FORMAT, @@ -242,7 +241,7 @@ define([ ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-75.59777, 40.03883))), new Cartesian3(0.0, 0.0, 3000000.0)), id : 'geometry3', attributes : { - color : new ColorGeometryInstanceAttribute(Color.BLANCHEDALMOND), + color : ColorGeometryInstanceAttribute.fromColor(Color.BLANCHEDALMOND), show : new ShowGeometryInstanceAttribute(true) } }); @@ -258,7 +257,7 @@ define([ }), id : 'geometry4', attributes : { - color : new ColorGeometryInstanceAttribute(new Color(1.0, 1.0, 0.0, 0.5)), + color : new ColorGeometryInstanceAttribute(1.0, 1.0, 0.0, 0.5), show : new ShowGeometryInstanceAttribute(true) } }); @@ -440,7 +439,7 @@ define([ }), id : 'customWithIndices', attributes : { - color : new ColorGeometryInstanceAttribute(new Color(1.0, 1.0, 1.0, 1.0)) + color : new ColorGeometryInstanceAttribute(1.0, 1.0, 1.0, 1.0) } }); scene.getPrimitives().add(new Primitive({ @@ -467,7 +466,7 @@ define([ }), id : 'customWithoutIndices', attributes : { - color : new ColorGeometryInstanceAttribute(new Color(1.0, 1.0, 0.0, 1.0)) + color : new ColorGeometryInstanceAttribute(1.0, 1.0, 0.0, 1.0) } }); scene.getPrimitives().add(new Primitive({ @@ -489,7 +488,7 @@ define([ ]) }), attributes : { - color : new ColorGeometryInstanceAttribute(new Color(1.0, 1.0, 1.0, 1.0)) + color : new ColorGeometryInstanceAttribute(1.0, 1.0, 1.0, 1.0) }, id : 'simple polyline' }), @@ -502,7 +501,7 @@ define([ ]) }), attributes : { - color : new ColorGeometryInstanceAttribute(new Color(1.0, 0.0, 1.0, 1.0)) + color : new ColorGeometryInstanceAttribute(1.0, 0.0, 1.0, 1.0) }, id : 'another simple polyline' }) diff --git a/Apps/Sandcastle/gallery/Geometry and Appearances.html b/Apps/Sandcastle/gallery/Geometry and Appearances.html index 5173ba8a2140..d076fd0cd4a5 100644 --- a/Apps/Sandcastle/gallery/Geometry and Appearances.html +++ b/Apps/Sandcastle/gallery/Geometry and Appearances.html @@ -122,7 +122,7 @@ vertexFormat : Cesium.PerInstanceColorAppearance.VERTEX_FORMAT }), attributes : { - color : new Cesium.ColorGeometryInstanceAttribute(new Cesium.Color(Math.random(), Math.random(), Math.random(), 0.5)) + color : new Cesium.ColorGeometryInstanceAttribute(Math.random(), Math.random(), Math.random(), 0.5) } })); @@ -133,7 +133,7 @@ vertexFormat : Cesium.PerInstanceColorAppearance.VERTEX_FORMAT }), attributes : { - color : new Cesium.ColorGeometryInstanceAttribute(new Cesium.Color(Math.random(), Math.random(), Math.random(), 0.5)) + color : new Cesium.ColorGeometryInstanceAttribute(Math.random(), Math.random(), Math.random(), 0.5) } })); } @@ -162,7 +162,7 @@ modelMatrix : Cesium.Matrix4.multiplyByUniformScale(Cesium.Matrix4.multiplyByTranslation(Cesium.Transforms.eastNorthUpToFixedFrame( ellipsoid.cartographicToCartesian(Cesium.Cartographic.fromDegrees(-105.0, 45.0))), new Cesium.Cartesian3(0.0, 0.0, height)), 90000.0), attributes : { - color : new Cesium.ColorGeometryInstanceAttribute(new Cesium.Color(Math.random(), Math.random(), Math.random(), 1.0)) + color : new Cesium.ColorGeometryInstanceAttribute(Math.random(), Math.random(), Math.random(), 1.0) } })); @@ -171,7 +171,7 @@ modelMatrix : Cesium.Matrix4.multiplyByUniformScale(Cesium.Matrix4.multiplyByTranslation(Cesium.Transforms.eastNorthUpToFixedFrame( ellipsoid.cartographicToCartesian(Cesium.Cartographic.fromDegrees(-102.0, 45.0))), new Cesium.Cartesian3(0.0, 0.0, height)), 90000.0), attributes : { - color : new Cesium.ColorGeometryInstanceAttribute(new Cesium.Color(Math.random(), Math.random(), Math.random(), 1.0)) + color : new Cesium.ColorGeometryInstanceAttribute(Math.random(), Math.random(), Math.random(), 1.0) } })); } @@ -199,7 +199,7 @@ ]) }), attributes : { - color : new Cesium.ColorGeometryInstanceAttribute(new Cesium.Color(Math.random(), Math.random(), Math.random(), 1.0)) + color : new Cesium.ColorGeometryInstanceAttribute(Math.random(), Math.random(), Math.random(), 1.0) } })); } @@ -212,7 +212,7 @@ depthTest : { enabled : true }, - lineWidth : 4.0 + //lineWidth : 4.0 //TODO: Fails with ANGLE } }) })); diff --git a/Source/Core/ColorGeometryInstanceAttribute.js b/Source/Core/ColorGeometryInstanceAttribute.js index 8cd5e16086ec..60b3bc56c40b 100644 --- a/Source/Core/ColorGeometryInstanceAttribute.js +++ b/Source/Core/ColorGeometryInstanceAttribute.js @@ -9,8 +9,6 @@ define([ ComponentDatatype) { "use strict"; - var defaultColor = new Color(1.0, 0.0, 0.0, 0.5); - /** * Value and type information for per-instance geometry color. * @@ -28,15 +26,18 @@ define([ * ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-0.0, 0.0))), new Cartesian3(0.0, 0.0, 1000000.0)), * id : 'box', * attributes : { - * color : new ColorGeometryInstanceAttribute(Color.AQUA) + * color : new ColorGeometryInstanceAttribute(red, green, blue, alpha) * } * }); * * @see GeometryInstance * @see GeometryInstanceAttribute */ - var ColorGeometryInstanceAttribute = function(color) { - color = defaultValue(color, defaultColor); + var ColorGeometryInstanceAttribute = function(red, green, blue, alpha) { + red = defaultValue(red, 1.0); + green = defaultValue(green, 1.0); + blue = defaultValue(blue, 1.0); + alpha = defaultValue(alpha, 1.0); /** * DOC_TBA @@ -56,19 +57,26 @@ define([ /** * DOC_TBA */ - this.value = ColorGeometryInstanceAttribute.toValue(color); + this.value = [ + Color.floatToByte(red), + Color.floatToByte(green), + Color.floatToByte(blue), + Color.floatToByte(alpha) + ]; + }; + + /** + * DOC_TBA + */ + ColorGeometryInstanceAttribute.fromColor = function(color) { + return new ColorGeometryInstanceAttribute(color.red, color.green, color.blue, color.alpha); }; /** * DOC_TBA */ ColorGeometryInstanceAttribute.toValue = function(color) { - return [ - Color.floatToByte(color.red), - Color.floatToByte(color.green), - Color.floatToByte(color.blue), - Color.floatToByte(color.alpha) - ]; + return color.toBytes(); }; return ColorGeometryInstanceAttribute; diff --git a/Source/Core/GeometryInstanceAttribute.js b/Source/Core/GeometryInstanceAttribute.js index 68aebe69479d..d308b266df01 100644 --- a/Source/Core/GeometryInstanceAttribute.js +++ b/Source/Core/GeometryInstanceAttribute.js @@ -130,7 +130,14 @@ define([ result.componentDatatype = instanceAttribute.componentDatatype; result.componentsPerAttribute = instanceAttribute.componentsPerAttribute; result.normalize = instanceAttribute.normalize; - result.value = instanceAttribute.value; + + var otherValue = instanceAttribute.value; + var length = otherValue.length; + var value = new Array(length); + for (var i = 0; i < length; ++i) { + value[i] = otherValue[i]; + } + result.value = value; return result; }; diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index b2792fa97e4f..3faf7be42534 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -99,7 +99,7 @@ define([ * }), * id : 'object returned when this instance is picked and to get/set per-instance attributes', * attribute : { - * color : new ColorGeometryInstanceAttribute(new Color(0.0, 1.0, 1.0, 0.5)) + * color : new ColorGeometryInstanceAttribute(0.0, 1.0, 1.0, 0.5) * } * }); * var ellipsoidInstance = new GeometryInstance({ @@ -111,7 +111,7 @@ define([ * ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-95.59777, 40.03883))), new Cartesian3(0.0, 0.0, 500000.0)), * id : 'object returned when this instance is picked and to get/set per-instance attributes', * attribute : { - * color : new ColorGeometryInstanceAttribute(new Color(1.0, 0.0, 1.0, 0.5)) + * color : ColorGeometryInstanceAttribute.fromColor(Color.AQUA) * } * }); * var primitive = new Primitive({ From 2df4507b77d51b3646827e6e97f6c9d019bedbc6 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Fri, 28 Jun 2013 16:07:38 -0400 Subject: [PATCH 268/306] Fixed Geometry Sandcastle example --- Apps/Sandcastle/gallery/Geometry and Appearances.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Apps/Sandcastle/gallery/Geometry and Appearances.html b/Apps/Sandcastle/gallery/Geometry and Appearances.html index f22f35cd40cc..3c91c9e86618 100644 --- a/Apps/Sandcastle/gallery/Geometry and Appearances.html +++ b/Apps/Sandcastle/gallery/Geometry and Appearances.html @@ -202,7 +202,7 @@ depthTest : { enabled : true }, - lineWidth : 4.0 + lineWidth : Math.min(4.0, scene.getContext().getMaximumAliasedLineWidth()) } }) })); From 2c4a2bc03d291ec1fc41c9f6675ed253146911d0 Mon Sep 17 00:00:00 2001 From: hpinkos Date: Fri, 28 Jun 2013 16:11:30 -0400 Subject: [PATCH 269/306] duplicate corner positions and correct wall geometry normals/tangents/binormals --- Source/Core/WallGeometry.js | 130 ++++++++++++++++++++++++------------ 1 file changed, 88 insertions(+), 42 deletions(-) diff --git a/Source/Core/WallGeometry.js b/Source/Core/WallGeometry.js index 235174881047..6fba5e364dfc 100644 --- a/Source/Core/WallGeometry.js +++ b/Source/Core/WallGeometry.js @@ -10,6 +10,7 @@ define([ './Ellipsoid', './EllipsoidTangentPlane', './GeometryAttribute', + './Math', './PolylinePipeline', './PolygonPipeline', './PrimitiveType', @@ -26,6 +27,7 @@ define([ Ellipsoid, EllipsoidTangentPlane, GeometryAttribute, + CesiumMath, PolylinePipeline, PolygonPipeline, PrimitiveType, @@ -36,6 +38,7 @@ define([ var scratchCartographic = new Cartographic(); var scratchCartesian3Position1 = new Cartesian3(); var scratchCartesian3Position2 = new Cartesian3(); + var scratchCartesian3Position3 = new Cartesian3(); var scratchBinormal = new Cartesian3(); var scratchTangent = new Cartesian3(); var scratchNormal = new Cartesian3(); @@ -80,7 +83,7 @@ define([ var wallPositions = options.positions; var terrain = options.terrain; var top = options.top; - var bottom = options.bottom; + var bottom = defaultValue(options.bottom, 0); var ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84); var vertexFormat = defaultValue(options.vertexFormat, VertexFormat.DEFAULT); @@ -102,15 +105,23 @@ define([ wallPositions.reverse(); } } - var i; - var size = wallPositions.length * 2; + var flatPositions = []; + var length = wallPositions.length; + for (i = 0; i < length - 1; i++) { + var p1 = wallPositions[i]; + var p2 = wallPositions[i+1]; + flatPositions.push(p1.x, p1.y, p1.z); + flatPositions.push(p2.x, p2.y, p2.z); + } + + var size = flatPositions.length * 2; - var positions = vertexFormat.position ? new Float64Array(size * 3) : undefined; - var normals = vertexFormat.normal ? new Float32Array(size * 3) : undefined; - var tangents = vertexFormat.tangent ? new Float32Array(size * 3) : undefined; - var binormals = vertexFormat.binormal ? new Float32Array(size * 3) : undefined; - var textureCoordinates = vertexFormat.st ? new Float32Array(size * 2) : undefined; + var positions = vertexFormat.position ? new Float64Array(size) : undefined; + var normals = vertexFormat.normal ? new Float32Array(size) : undefined; + var tangents = vertexFormat.tangent ? new Float32Array(size) : undefined; + var binormals = vertexFormat.binormal ? new Float32Array(size) : undefined; + var textureCoordinates = vertexFormat.st ? new Float32Array(size / 3 * 2) : undefined; var positionIndex = 0; var normalIndex = 0; @@ -120,9 +131,14 @@ define([ // add lower and upper points one after the other, lower // points being even and upper points being odd - var length = wallPositions.length; - for (i = 0; i < length; ++i) { - var c = ellipsoid.cartesianToCartographic(wallPositions[i], scratchCartographic); + length = flatPositions.length; + var normal = scratchNormal; + var tangent = scratchTangent; + var binormal = scratchBinormal; + var recomputeNormal = true; + for (i = 0; i < length; i += 3) { + var pos = Cartesian3.fromArray(flatPositions, i, scratchCartesian3Position1); + var c = ellipsoid.cartesianToCartographic(pos, scratchCartographic); var origHeight = c.height; c.height = 0.0; @@ -134,17 +150,16 @@ define([ } } - if (bottom !== undefined) { - c.height = bottom; - } else { - c.height += terrainHeight; - } - + c.height = bottom + terrainHeight; var bottomPosition = ellipsoid.cartographicToCartesian(c, scratchCartesian3Position1); // get the original height back, or set the top value - c.height = (top === undefined) ? origHeight : top; - c.height += terrainHeight; + if (typeof top !== 'undefined') { + c.height = top + terrain.height; + } else { + c.height = origHeight + terrainHeight; + } + var topPosition = ellipsoid.cartographicToCartesian(c, scratchCartesian3Position2); if (vertexFormat.position) { @@ -160,29 +175,53 @@ define([ } if (vertexFormat.normal || vertexFormat.tangent || vertexFormat.binormal) { - var fromPrevious = (i === 0) ? Cartesian3.ZERO : Cartesian3.subtract(wallPositions[i], wallPositions[i - 1], scratchCartesian3Position1); - var toNext = (i === length - 1) ? Cartesian3.ZERO : Cartesian3.subtract(wallPositions[i + 1], wallPositions[i], scratchCartesian3Position2); + var nextPosition; + if (i+3 < length) { + nextPosition = Cartesian3.fromArray(flatPositions, i+3, scratchCartesian3Position3); + } + + if (recomputeNormal) { + nextPosition = nextPosition.subtract(topPosition, nextPosition); + bottomPosition = bottomPosition.subtract(topPosition, bottomPosition); + normal = Cartesian3.cross(bottomPosition, nextPosition, normal).normalize(normal); + if (vertexFormat.tangent) { + tangent = nextPosition.normalize(tangent); + } + if (vertexFormat.binormal) { + binormal = Cartesian3.cross(normal, tangent, binormal).normalize(binormal); + } + recomputeNormal = false; + } - var tangent = Cartesian3.add(fromPrevious, toNext, scratchTangent); - var binormal = Cartesian3.subtract(topPosition, bottomPosition, scratchBinormal); + if (topPosition.equalsEpsilon(nextPosition, CesiumMath.EPSILON4)) { // if we've reached a corner + recomputeNormal = true; + } if (vertexFormat.normal) { - var normal = Cartesian3.cross(tangent, binormal, scratchNormal); - Cartesian3.normalize(normal, normal); + normals[normalIndex++] = normal.x; + normals[normalIndex++] = normal.y; + normals[normalIndex++] = normal.z; + normals[normalIndex++] = normal.x; normals[normalIndex++] = normal.y; normals[normalIndex++] = normal.z; } if (vertexFormat.tangent) { - Cartesian3.normalize(tangent, tangent); + tangents[tangentIndex++] = tangent.x; + tangents[tangentIndex++] = tangent.y; + tangents[tangentIndex++] = tangent.z; + tangents[tangentIndex++] = tangent.x; tangents[tangentIndex++] = tangent.y; tangents[tangentIndex++] = tangent.z; } if (vertexFormat.binormal) { - Cartesian3.normalize(binormal, binormal); + binormals[binormalIndex++] = binormal.x; + binormals[binormalIndex++] = binormal.y; + binormals[binormalIndex++] = binormal.z; + binormals[binormalIndex++] = binormal.x; binormals[binormalIndex++] = binormal.y; binormals[binormalIndex++] = binormal.z; @@ -257,21 +296,28 @@ define([ // C (i) D (i+2) F // - length = size; - size -= 2; - var indices = IndexDatatype.createTypedArray(length, size * 3); - - var j = 0; - for (i = 0; i < size; i += 2) { - // first do A C B - indices[j++] = i + 1; - indices[j++] = i; - indices[j++] = i + 3; - - // now do B C D - indices[j++] = i + 3; - indices[j++] = i; - indices[j++] = i + 2; + var numVertices = size/3; + size -= 6; + var indices = IndexDatatype.createTypedArray(numVertices, size); + + var edgeIndex = 0; + for (i = 0; i < numVertices - 2; i += 2) { + var LL = i; + var LR = i + 2; + var pl = Cartesian3.fromArray(positions, LL*3, scratchCartesian3Position1); + var pr = Cartesian3.fromArray(positions, LR*3, scratchCartesian3Position2); + if (Cartesian3.equalsEpsilon(pl, pr, CesiumMath.EPSILON6)) { + continue; + } + var UL = i + 1; + var UR = i + 3; + + indices[edgeIndex++] = UL; + indices[edgeIndex++] = LL; + indices[edgeIndex++] = UR; + indices[edgeIndex++] = UR; + indices[edgeIndex++] = LL; + indices[edgeIndex++] = LR; } /** From a19c2a4d1da9679bc5d41cd3f56c5641200ed4c3 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Fri, 28 Jun 2013 16:32:00 -0400 Subject: [PATCH 270/306] Update Primitive based on review. --- Source/Scene/Primitive.js | 113 +++++++++++++++++++++++++------------- 1 file changed, 75 insertions(+), 38 deletions(-) diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index 3faf7be42534..bf9dc97d8137 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -193,6 +193,8 @@ define([ this._allowColumbusView = defaultValue(options.allowColumbusView, true); this._boundingSphere = undefined; this._boundingSphere2D = undefined; + this._perInstanceAttributes = undefined; + this._perInstanceAttributesCache = {}; this._va = []; this._attributeIndices = undefined; @@ -459,7 +461,11 @@ define([ } if (typeof indices[instance.id][name] === 'undefined') { - indices[instance.id][name] = []; + indices[instance.id][name] = { + dirty : false, + value : instance.attributes[name].value, + indices : [] + }; } var size = attribute.vertexBuffer.getSizeInBytes() / attribute.componentDatatype.sizeInBytes; @@ -469,20 +475,18 @@ define([ var count; if (offset + tempVertexCount < size) { count = tempVertexCount; - indices[instance.id][name].push({ + indices[instance.id][name].indices.push({ attribute : attribute, offset : offset, - count : count, - value : instance.attributes[name].value + count : count }); offsets[name] = offset + tempVertexCount; } else { count = size - offset; - indices[instance.id][name].push({ + indices[instance.id][name].indices.push({ attribute : attribute, offset : offset, - count : count, - value : instance.attributes[name].value + count : count }); offsets[name] = 0; vaIndices[name] = vaIndex + 1; @@ -555,15 +559,16 @@ define([ return vertexShaderSource; } - var glPositionIndex = vertexShaderSource.indexOf('gl_Position'); - var semicolonIndex = vertexShaderSource.indexOf(';', glPositionIndex); - - var source = + var renamedVS = vertexShaderSource.replace(/void\s+main\s*\(\s*(?:void)?\s*\)/g, 'void czm_non_show_main()'); + var showMain = 'attribute float show;\n' + - vertexShaderSource.substring(0, semicolonIndex) + - ' * show' + - vertexShaderSource.substring(semicolonIndex); - return source; + 'void main() \n' + + '{ \n' + + ' czm_non_show_main(); \n' + + ' gl_Position *= show; \n' + + '}'; + + return renamedVS + '\n' + showMain; } function validateShaderMatching(shaderProgram, attributeIndices) { @@ -726,6 +731,47 @@ define([ } } + // Update per-instance attributes + if (this._perInstanceAttributes._dirty) { + var perInstance = this._perInstanceAttributes; + for (var id in perInstance) { + if (perInstance.hasOwnProperty(id) && id !== '_dirty') { + var perInstanceAttributes = perInstance[id]; + for (var name in perInstanceAttributes) { + if (perInstanceAttributes.hasOwnProperty(name)) { + var attribute = perInstanceAttributes[name]; + if (attribute.dirty) { + var value = attribute.value; + var indices = attribute.indices; + length = indices.length; + for (i = 0; i < length; ++i) { + var index = indices[i]; + var offset = index.offset; + var count = index.count; + + var vaAttribute = index.attribute; + var componentDatatype = vaAttribute.componentDatatype; + var componentsPerAttribute = vaAttribute.componentsPerAttribute; + + var typedArray = componentDatatype.createTypedArray(count * componentsPerAttribute); + for (var j = 0; j < count; ++j) { + typedArray.set(value, j * componentsPerAttribute); + } + + var offsetInBytes = offset * componentsPerAttribute * componentDatatype.sizeInBytes; + vaAttribute.vertexBuffer.copyFromArrayView(typedArray, offsetInBytes); + } + + attribute.dirty = false; + } + } + } + } + } + + this._perInstanceAttributes._dirty = false; + } + var boundingSphere; if (frameState.mode === SceneMode.SCENE3D) { boundingSphere = this._boundingSphere; @@ -753,35 +799,19 @@ define([ function createGetFunction(name, perInstanceAttributes) { return function() { - return perInstanceAttributes[name][0].value; + return perInstanceAttributes[name].value; }; } - function createSetFunction(name, perInstanceAttributes) { + function createSetFunction(name, perInstanceAttributes, container) { return function (value) { if (typeof value === 'undefined' || typeof value.length === 'undefined' || value.length < 1 || value.length > 4) { throw new DeveloperError('value must be and array with length between 1 and 4.'); } - var indices = perInstanceAttributes[name]; - var length = indices.length; - for (var i = 0; i < length; ++i) { - var index = indices[i]; - var offset = index.offset; - var count = index.count; - - var attribute = index.attribute; - var componentDatatype = attribute.componentDatatype; - var componentsPerAttribute = attribute.componentsPerAttribute; - - var typedArray = componentDatatype.createTypedArray(count * componentsPerAttribute); - for (var j = 0; j < count; ++j) { - typedArray.set(value, j * componentsPerAttribute); - } - - var offsetInBytes = offset * componentsPerAttribute * componentDatatype.sizeInBytes; - attribute.vertexBuffer.copyFromArrayView(typedArray, offsetInBytes); - } + perInstanceAttributes[name].value = value; + perInstanceAttributes[name].dirty = true; + container._dirty = true; }; } @@ -793,18 +823,25 @@ define([ throw new DeveloperError('id is required'); } + var cachedObject = this._perInstanceAttributesCache[id]; + if (typeof cachedObject !== 'undefined') { + return cachedObject; + } + var perInstanceAttributes = this._perInstanceAttributes[id]; var attributes = {}; for (var name in perInstanceAttributes) { if (perInstanceAttributes.hasOwnProperty(name)) { Object.defineProperty(attributes, name, { - get : createGetFunction(name, perInstanceAttributes), - set : createSetFunction(name, perInstanceAttributes) + get : createGetFunction(name, perInstanceAttributes, this._perInstanceAttributes), + set : createSetFunction(name, perInstanceAttributes, this._perInstanceAttributes) }); } } + this._perInstanceAttributesCache[id] = attributes; + return attributes; }; From 586cef9df2a12a5fe24a322063bac70827f74d23 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Fri, 28 Jun 2013 16:47:59 -0400 Subject: [PATCH 271/306] Add error checking and change GeometryInstanceAttribute to use typed arrays to be consistent. --- Source/Core/ColorGeometryInstanceAttribute.js | 20 ++++++++++++++----- Source/Core/GeometryInstanceAttribute.js | 13 ++---------- Source/Core/ShowGeometryInstanceAttribute.js | 12 ++++++++--- 3 files changed, 26 insertions(+), 19 deletions(-) diff --git a/Source/Core/ColorGeometryInstanceAttribute.js b/Source/Core/ColorGeometryInstanceAttribute.js index 60b3bc56c40b..2a80f3e8f5f1 100644 --- a/Source/Core/ColorGeometryInstanceAttribute.js +++ b/Source/Core/ColorGeometryInstanceAttribute.js @@ -2,11 +2,13 @@ define([ './defaultValue', './Color', - './ComponentDatatype' + './ComponentDatatype', + './DeveloperError' ], function( defaultValue, Color, - ComponentDatatype) { + ComponentDatatype, + DeveloperError) { "use strict"; /** @@ -57,18 +59,22 @@ define([ /** * DOC_TBA */ - this.value = [ + this.value = new Uint8Array([ Color.floatToByte(red), Color.floatToByte(green), Color.floatToByte(blue), Color.floatToByte(alpha) - ]; + ]); }; /** * DOC_TBA */ ColorGeometryInstanceAttribute.fromColor = function(color) { + if (typeof color === 'undefined') { + throw new DeveloperError('color is required.'); + } + return new ColorGeometryInstanceAttribute(color.red, color.green, color.blue, color.alpha); }; @@ -76,7 +82,11 @@ define([ * DOC_TBA */ ColorGeometryInstanceAttribute.toValue = function(color) { - return color.toBytes(); + if (typeof color === 'undefined') { + throw new DeveloperError('color is required.'); + } + + return new Uint8Array(color.toBytes()); }; return ColorGeometryInstanceAttribute; diff --git a/Source/Core/GeometryInstanceAttribute.js b/Source/Core/GeometryInstanceAttribute.js index d308b266df01..b2531597ab4f 100644 --- a/Source/Core/GeometryInstanceAttribute.js +++ b/Source/Core/GeometryInstanceAttribute.js @@ -99,8 +99,6 @@ define([ * every three elements in values defines one attributes since * componentsPerAttribute is 3. * - * @type Array - * * @default undefined * * @example @@ -108,7 +106,7 @@ define([ * componentDatatype : ComponentDatatype.UNSIGNED_BYTE, * componentsPerAttribute : 1, * normalize : true, - * value : 1.0 + * value : [1.0] * } */ this.value = options.value; @@ -130,14 +128,7 @@ define([ result.componentDatatype = instanceAttribute.componentDatatype; result.componentsPerAttribute = instanceAttribute.componentsPerAttribute; result.normalize = instanceAttribute.normalize; - - var otherValue = instanceAttribute.value; - var length = otherValue.length; - var value = new Array(length); - for (var i = 0; i < length; ++i) { - value[i] = otherValue[i]; - } - result.value = value; + result.value = new instanceAttribute.value.constructor(instanceAttribute.value); return result; }; diff --git a/Source/Core/ShowGeometryInstanceAttribute.js b/Source/Core/ShowGeometryInstanceAttribute.js index 3f27ade5f85e..d883a74469cc 100644 --- a/Source/Core/ShowGeometryInstanceAttribute.js +++ b/Source/Core/ShowGeometryInstanceAttribute.js @@ -1,10 +1,12 @@ /*global define*/ define([ './defaultValue', - './ComponentDatatype' + './ComponentDatatype', + './DeveloperError' ], function( defaultValue, - ComponentDatatype) { + ComponentDatatype, + DeveloperError) { "use strict"; /** @@ -60,7 +62,11 @@ define([ * DOC_TBA */ ShowGeometryInstanceAttribute.toValue = function(show) { - return [show]; + if (typeof show === 'undefined') { + throw new DeveloperError('show is required.'); + } + + return new Uint8Array([show]); }; return ShowGeometryInstanceAttribute; From c1cdc2cf2b6a7622d3b22e53b671406a6b0ba69f Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Fri, 28 Jun 2013 17:08:45 -0400 Subject: [PATCH 272/306] More reference doc --- Source/Core/ColorGeometryInstanceAttribute.js | 45 ++++++++++++++++--- Source/Core/GeometryInstance.js | 11 ++++- Source/Core/ShowGeometryInstanceAttribute.js | 45 ++++++++++++++++--- Source/Scene/Primitive.js | 13 +++++- 4 files changed, 101 insertions(+), 13 deletions(-) diff --git a/Source/Core/ColorGeometryInstanceAttribute.js b/Source/Core/ColorGeometryInstanceAttribute.js index 2a80f3e8f5f1..843384f3d8e6 100644 --- a/Source/Core/ColorGeometryInstanceAttribute.js +++ b/Source/Core/ColorGeometryInstanceAttribute.js @@ -42,22 +42,47 @@ define([ alpha = defaultValue(alpha, 1.0); /** - * DOC_TBA + * The datatype of each component in the attribute, e.g., individual elements in + * {@link ColorGeometryInstanceAttribute#value}. + * + * @type ComponentDatatype + * + * @default {@link ComponentDatatype.UNSIGNED_BYTE} + * + * @readonly */ this.componentDatatype = ComponentDatatype.UNSIGNED_BYTE; /** - * DOC_TBA + * The number of components in the attributes, i.e., {@link ColorGeometryInstanceAttribute#value}. + * + * @type Number + * + * @default 4 + * + * @readonly */ this.componentsPerAttribute = 4; /** - * DOC_TBA + * When true and componentDatatype is an integer format, + * indicate that the components should be mapped to the range [0, 1] (unsigned) + * or [-1, 1] (signed) when they are accessed as floating-point for rendering. + * + * @type Boolean + * + * @default true + * + * @readonly */ this.normalize = true; /** - * DOC_TBA + * The values for the attributes stored in a typed array. + * + * @type Uint8Array + * + * @default [1.0, 0.0, 0.0, 0.5] */ this.value = new Uint8Array([ Color.floatToByte(red), @@ -79,7 +104,17 @@ define([ }; /** - * DOC_TBA + * Converts a color to a typed array that can be used to assign a color attribute. + * + * @param {Color} color The color. + * + * @returns {Uint8Array} The typed array in the attribute's format. + * + * @exception {DeveloperError} color is required. + * + * @example + * var attributes = primitive.getGeometryInstanceAttributes('an id'); + * attributes.color = ColorGeometryInstanceAttribute.toValue(Color.AQUA); */ ColorGeometryInstanceAttribute.toValue = function(color) { if (typeof color === 'undefined') { diff --git a/Source/Core/GeometryInstance.js b/Source/Core/GeometryInstance.js index 67a9eb74bc81..d2219658e897 100644 --- a/Source/Core/GeometryInstance.js +++ b/Source/Core/GeometryInstance.js @@ -23,7 +23,7 @@ define([ * @param {Geometry} [options.geometry=undefined] The geometry to instance. * @param {Matrix4} [options.modelMatrix=Matrix4.IDENTITY] The model matrix that transforms to transform the geometry from model to world coordinates. * @param {Object} [options.id=undefined] A user-defined object to return when the instance is picked with {@link Context#pick} or get/set per-instance attributes with {@link Primitive#getGeometryInstanceAttributes}. - * @param {Object} [options.attributes] DOC_TBA + * @param {Object} [options.attributes] Per-instance attributes like a show or color attribute shown in the example below. * * @example * // Create geometry for a box, and two instances that refer to it. @@ -81,6 +81,8 @@ define([ /** * User-defined object returned when the instance is picked or used to get/set per-instance attributes. * + * @type Object + * * @default undefined * * @see Context#pick @@ -89,7 +91,12 @@ define([ this.id = options.id; /** - * DOC_TBA + * Per-instance attributes like {@link ColorGeometryInstanceAttribute} or {@link ShowGeometryInstanceAttribute}. + * {@link Geometry} attributes varying per vertex; these attributes are constant for the entire instance. + * + * @type Object + * + * @default undefined */ this.attributes = defaultValue(options.attributes, {}); }; diff --git a/Source/Core/ShowGeometryInstanceAttribute.js b/Source/Core/ShowGeometryInstanceAttribute.js index d883a74469cc..c82a823ed5b8 100644 --- a/Source/Core/ShowGeometryInstanceAttribute.js +++ b/Source/Core/ShowGeometryInstanceAttribute.js @@ -38,28 +38,63 @@ define([ show = defaultValue(show, true); /** - * DOC_TBA + * The datatype of each component in the attribute, e.g., individual elements in + * {@link ShowGeometryInstanceAttribute#value}. + * + * @type ComponentDatatype + * + * @default {@link ComponentDatatype.UNSIGNED_BYTE} + * + * @readonly */ this.componentDatatype = ComponentDatatype.UNSIGNED_BYTE; /** - * DOC_TBA + * The number of components in the attributes, i.e., {@link ShowGeometryInstanceAttribute#value}. + * + * @type Number + * + * @default 1 + * + * @readonly */ this.componentsPerAttribute = 1; /** - * DOC_TBA + * When true and componentDatatype is an integer format, + * indicate that the components should be mapped to the range [0, 1] (unsigned) + * or [-1, 1] (signed) when they are accessed as floating-point for rendering. + * + * @type Boolean + * + * @default true + * + * @readonly */ this.normalize = true; /** - * DOC_TBA + * The values for the attributes stored in a typed array. + * + * @type Uint8Array + * + * @default [1.0] */ this.value = ShowGeometryInstanceAttribute.toValue(show); }; /** - * DOC_TBA + * Converts a boolean show to a typed array that can be used to assign a show attribute. + * + * @param {Boolean} show The show value. + * + * @returns {Uint8Array} The typed array in the attribute's format. + * + * @exception {DeveloperError} show is required. + * + * @example + * var attributes = primitive.getGeometryInstanceAttributes('an id'); + * attributes.show = ShowGeometryInstanceAttribute.toValue(true); */ ShowGeometryInstanceAttribute.toValue = function(show) { if (typeof show === 'undefined') { diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index bf9dc97d8137..f43631352f75 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -816,7 +816,18 @@ define([ } /** - * DOC_TBA + * Returns the modifiable per-instance attributes for a {@link GeometryInstance}. + * + * @param {Object} id The id of the {@link GeometryInstance}. + * + * @returns {Object} The typed array in the attribute's format. + * + * @exception {DeveloperError} id is required. + * + * @example + * var attributes = primitive.getGeometryInstanceAttributes('an id'); + * attributes.color = ColorGeometryInstanceAttribute.toValue(Color.AQUA); + * attributes.show = ShowGeometryInstanceAttribute.toValue(true); */ Primitive.prototype.getGeometryInstanceAttributes = function(id) { if (typeof id === 'undefined') { From 941bdea5028c995c9fe3de6de1aec2f947dcf55d Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Fri, 28 Jun 2013 17:13:57 -0400 Subject: [PATCH 273/306] Fix colors for tangent space debugging --- Source/Scene/createTangentSpaceDebugPrimitive.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Source/Scene/createTangentSpaceDebugPrimitive.js b/Source/Scene/createTangentSpaceDebugPrimitive.js index 2d7b1a720348..f1ba8ba0167e 100644 --- a/Source/Scene/createTangentSpaceDebugPrimitive.js +++ b/Source/Scene/createTangentSpaceDebugPrimitive.js @@ -1,7 +1,6 @@ /*global define*/ define([ '../Core/DeveloperError', - '../Core/Color', '../Core/ColorGeometryInstanceAttribute', '../Core/GeometryInstance', '../Core/GeometryPipeline', @@ -9,7 +8,6 @@ define([ './PerInstanceColorAppearance' ], function( DeveloperError, - Color, ColorGeometryInstanceAttribute, GeometryInstance, GeometryPipeline, @@ -58,7 +56,7 @@ define([ instances.push(new GeometryInstance({ geometry : GeometryPipeline.createLineSegmentsForVectors(geometry, 'normal', length), attributes : { - color : new ColorGeometryInstanceAttribute(new Color(1.0, 0.0, 0.0, 1.0)) + color : new ColorGeometryInstanceAttribute(1.0, 0.0, 0.0, 1.0) }, modelMatrix : modelMatrix })); @@ -68,7 +66,7 @@ define([ instances.push(new GeometryInstance({ geometry : GeometryPipeline.createLineSegmentsForVectors(geometry, 'binormal', length), attributes : { - color : new ColorGeometryInstanceAttribute(new Color(0.0, 1.0, 0.0, 1.0)) + color : new ColorGeometryInstanceAttribute(0.0, 1.0, 0.0, 1.0) }, modelMatrix : modelMatrix })); @@ -78,7 +76,7 @@ define([ instances.push(new GeometryInstance({ geometry : GeometryPipeline.createLineSegmentsForVectors(geometry, 'tangent', length), attributes : { - color : new ColorGeometryInstanceAttribute(new Color(0.0, 0.0, 1.0, 1.0)) + color : new ColorGeometryInstanceAttribute(0.0, 0.0, 1.0, 1.0) }, modelMatrix : modelMatrix })); From 3e7b42f6d1ab04997107763e0d4388a413912403 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Fri, 28 Jun 2013 17:16:25 -0400 Subject: [PATCH 274/306] Fix Animations and Materials Sandcastle examples. --- Apps/Sandcastle/gallery/Animations.html | 51 +++----- Apps/Sandcastle/gallery/Materials.html | 167 ++++++++++++------------ 2 files changed, 102 insertions(+), 116 deletions(-) diff --git a/Apps/Sandcastle/gallery/Animations.html b/Apps/Sandcastle/gallery/Animations.html index b739719eff0f..d8f3bf6e981c 100644 --- a/Apps/Sandcastle/gallery/Animations.html +++ b/Apps/Sandcastle/gallery/Animations.html @@ -34,7 +34,7 @@ { "use strict"; - var polygon; + var extent; var rectangularSensor; function addAlphaAnimation(primitive, scene) { @@ -49,22 +49,14 @@ }); } - function addHeightAnimation(primitive, scene) { - Sandcastle.declare(addHeightAnimation); // For highlighting in Sandcastle. - scene.getAnimations().addProperty(primitive, 'height', 5000000.0, 0.0, { - duration : 1000 - }); - } - function addStripeAnimation(primitive, scene) { Sandcastle.declare(addStripeAnimation); // For highlighting in Sandcastle. scene.getAnimations().addOffsetIncrement(primitive.material); } - function resetPolygonPropeties(polygon) { - polygon.height = 0.0; - polygon.material.uniforms.time = 1.0; - polygon.material.uniforms.color = new Cesium.Color(1.0, 0.0, 0.0, 0.5); + function resetExtentPropeties(extent) { + extent.material.uniforms.time = 1.0; + extent.material.uniforms.color = new Cesium.Color(1.0, 0.0, 0.0, 0.5); } function createPrimitives(widget) { @@ -72,14 +64,15 @@ var scene = widget.scene; var primitives = scene.getPrimitives(); - polygon = new Cesium.Polygon(); - polygon.configureExtent(new Cesium.Extent( - Cesium.Math.toRadians(-120.0), - Cesium.Math.toRadians(20.0), - Cesium.Math.toRadians(-80.0), - Cesium.Math.toRadians(50.0))); - polygon.material = Cesium.Material.fromType(scene.getContext(), 'Erosion'); - primitives.add(polygon); + extent = new Cesium.ExtentPrimitive({ + extent : new Cesium.Extent( + Cesium.Math.toRadians(-120.0), + Cesium.Math.toRadians(20.0), + Cesium.Math.toRadians(-80.0), + Cesium.Math.toRadians(50.0)), + material : Cesium.Material.fromType(scene.getContext(), 'Erosion') + }); + primitives.add(extent); var modelMatrix = Cesium.Transforms.northEastDownToFixedFrame( ellipsoid.cartographicToCartesian(Cesium.Cartographic.fromDegrees(-45.0, 45.0))); @@ -105,8 +98,8 @@ label : 'Alpha Animation', onClick : function() { scene.getAnimations().removeAll(); - resetPolygonPropeties(polygon); - addAlphaAnimation(polygon, scene); + resetExtentPropeties(extent); + addAlphaAnimation(extent, scene); Sandcastle.highlight(addAlphaAnimation); } }).placeAt('toolbar'); @@ -115,22 +108,12 @@ label : 'Erosion Animation', onClick : function() { scene.getAnimations().removeAll(); - resetPolygonPropeties(polygon); - addErosionAnimation(polygon, scene); + resetExtentPropeties(extent); + addErosionAnimation(extent, scene); Sandcastle.highlight(addErosionAnimation); } }).placeAt('toolbar'); - new Button({ - label : 'Height Animation', - onClick : function() { - scene.getAnimations().removeAll(); - resetPolygonPropeties(polygon); - addHeightAnimation(polygon, scene); - Sandcastle.highlight(addHeightAnimation); - } - }).placeAt('toolbar'); - new Button({ label : 'Stripe Animation', onClick : function() { diff --git a/Apps/Sandcastle/gallery/Materials.html b/Apps/Sandcastle/gallery/Materials.html index 8b2f7bc8c381..b2a87aad0021 100644 --- a/Apps/Sandcastle/gallery/Materials.html +++ b/Apps/Sandcastle/gallery/Materials.html @@ -35,8 +35,8 @@ { "use strict"; - var polygon; - var worldPolygon; + var extent; + var worldExtent; var polyline; function applyAlphaMapMaterial(primitive, scene) { @@ -496,29 +496,29 @@ var compositeMaterialMenu = new DropDownMenu({ style: "display: none;"}); var polylineMaterialMenu = new DropDownMenu({ style: "display: none;"}); - function togglePolygonVisibility() { - polygon.show = true; - worldPolygon.show = false; + function toggleExtentVisibility() { + extent.show = true; + worldExtent.show = false; polyline.setShow(false); } - function toggleWorldPolygonVisibility() { - worldPolygon.show = true; - polygon.show = false; + function toggleWorldExtentVisibility() { + worldExtent.show = true; + extent.show = false; polyline.setShow(false); } function togglePolylineVisibility() { polyline.setShow(true); - worldPolygon.show = false; - polygon.show = false; + worldExtent.show = false; + extent.show = false; } baseMaterialMenu.addChild(new MenuItem({ label: 'Alpha Map', onClick: function() { - togglePolygonVisibility(); - applyAlphaMapMaterial(polygon, scene); + toggleExtentVisibility(); + applyAlphaMapMaterial(extent, scene); Sandcastle.highlight(applyAlphaMapMaterial); } })); @@ -526,8 +526,8 @@ proceduralTextureMenu.addChild(new MenuItem({ label: 'Asphalt', onClick: function() { - togglePolygonVisibility(); - applyAsphaltMaterial(polygon, scene); + toggleExtentVisibility(); + applyAsphaltMaterial(extent, scene); Sandcastle.highlight(applyAsphaltMaterial); } })); @@ -535,8 +535,8 @@ proceduralTextureMenu.addChild(new MenuItem({ label: 'Blob', onClick: function() { - togglePolygonVisibility(); - applyBlobMaterial(polygon, scene); + toggleExtentVisibility(); + applyBlobMaterial(extent, scene); Sandcastle.highlight(applyBlobMaterial); } })); @@ -544,8 +544,8 @@ proceduralTextureMenu.addChild(new MenuItem({ label: 'Brick', onClick: function() { - togglePolygonVisibility(); - applyBrickMaterial(polygon, scene); + toggleExtentVisibility(); + applyBrickMaterial(extent, scene); Sandcastle.highlight(applyBrickMaterial); } })); @@ -553,8 +553,8 @@ baseMaterialMenu.addChild(new MenuItem({ label: 'Bump Map', onClick: function() { - togglePolygonVisibility(); - applyBumpMapMaterial(polygon, scene); + toggleExtentVisibility(); + applyBumpMapMaterial(extent, scene); Sandcastle.highlight(applyBumpMapMaterial); } })); @@ -562,8 +562,8 @@ proceduralTextureMenu.addChild(new MenuItem({ label: 'Cement', onClick: function() { - togglePolygonVisibility(); - applyCementMaterial(polygon, scene); + toggleExtentVisibility(); + applyCementMaterial(extent, scene); Sandcastle.highlight(applyCementMaterial); } })); @@ -571,8 +571,8 @@ proceduralTextureMenu.addChild(new MenuItem({ label: 'Checkerboard', onClick: function() { - togglePolygonVisibility(); - applyCheckerboardMaterial(polygon, scene); + toggleExtentVisibility(); + applyCheckerboardMaterial(extent, scene); Sandcastle.highlight(applyCheckerboardMaterial); } })); @@ -580,8 +580,8 @@ compositeMaterialMenu.addChild(new MenuItem({ label: 'Composite Example 1', onClick: function() { - togglePolygonVisibility(); - applyCompositeMaterial1(polygon, scene); + toggleExtentVisibility(); + applyCompositeMaterial1(extent, scene); Sandcastle.highlight(applyCompositeMaterial1); } })); @@ -589,8 +589,8 @@ compositeMaterialMenu.addChild(new MenuItem({ label: 'Composite Example 2', onClick: function() { - toggleWorldPolygonVisibility(); - applyCompositeMaterial2(worldPolygon, scene); + toggleWorldExtentVisibility(); + applyCompositeMaterial2(worldExtent, scene); Sandcastle.highlight(applyCompositeMaterial2); } })); @@ -598,8 +598,8 @@ commonMaterialMenu.addChild(new MenuItem({ label: 'Color', onClick: function() { - togglePolygonVisibility(); - applyColorMaterial(polygon, scene); + toggleExtentVisibility(); + applyColorMaterial(extent, scene); Sandcastle.highlight(applyColorMaterial); } })); @@ -607,8 +607,8 @@ baseMaterialMenu.addChild(new MenuItem({ label: 'Diffuse', onClick: function() { - togglePolygonVisibility(); - applyDiffuseMaterial(polygon, scene); + toggleExtentVisibility(); + applyDiffuseMaterial(extent, scene); Sandcastle.highlight(applyDiffuseMaterial); } })); @@ -616,8 +616,8 @@ proceduralTextureMenu.addChild(new MenuItem({ label: 'Dot', onClick: function() { - togglePolygonVisibility(); - applyDotMaterial(polygon, scene); + toggleExtentVisibility(); + applyDotMaterial(extent, scene); Sandcastle.highlight(applyDotMaterial); } })); @@ -625,8 +625,8 @@ baseMaterialMenu.addChild(new MenuItem({ label: 'Emission Map', onClick: function() { - togglePolygonVisibility(); - applyEmissionMapMaterial(polygon, scene); + toggleExtentVisibility(); + applyEmissionMapMaterial(extent, scene); Sandcastle.highlight(applyEmissionMapMaterial); } })); @@ -634,8 +634,8 @@ proceduralTextureMenu.addChild(new MenuItem({ label: 'Facet', onClick: function() { - togglePolygonVisibility(); - applyFacetMaterial(polygon, scene); + toggleExtentVisibility(); + applyFacetMaterial(extent, scene); Sandcastle.highlight(applyFacetMaterial); } })); @@ -643,8 +643,8 @@ baseMaterialMenu.addChild(new MenuItem({ label: 'Fresnel', onClick: function() { - toggleWorldPolygonVisibility(); - applyFresnelMaterial(worldPolygon, scene); + toggleWorldExtentVisibility(); + applyFresnelMaterial(worldExtent, scene); Sandcastle.highlight(applyFresnelMaterial); } })); @@ -652,8 +652,8 @@ proceduralTextureMenu.addChild(new MenuItem({ label: 'Grass', onClick: function() { - togglePolygonVisibility(); - applyGrassMaterial(polygon, scene); + toggleExtentVisibility(); + applyGrassMaterial(extent, scene); Sandcastle.highlight(applyGrassMaterial); } })); @@ -661,8 +661,8 @@ proceduralTextureMenu.addChild(new MenuItem({ label: 'Grid', onClick: function() { - togglePolygonVisibility(polygon, worldPolygon); - applyGridMaterial(polygon, scene); + toggleExtentVisibility(extent, worldExtent); + applyGridMaterial(extent, scene); Sandcastle.highlight(applyGridMaterial); } })); @@ -670,8 +670,8 @@ commonMaterialMenu.addChild(new MenuItem({ label: 'Image', onClick: function() { - togglePolygonVisibility(); - applyImageMaterial(polygon, scene); + toggleExtentVisibility(); + applyImageMaterial(extent, scene); Sandcastle.highlight(applyImageMaterial); } })); @@ -679,8 +679,8 @@ baseMaterialMenu.addChild(new MenuItem({ label: 'Normal Map', onClick: function() { - togglePolygonVisibility(); - applyNormalMapMaterial(polygon, scene); + toggleExtentVisibility(); + applyNormalMapMaterial(extent, scene); Sandcastle.highlight(applyNormalMapMaterial); } })); @@ -688,8 +688,8 @@ baseMaterialMenu.addChild(new MenuItem({ label: 'Reflection', onClick: function() { - toggleWorldPolygonVisibility(); - applyReflectionMaterial(worldPolygon, scene); + toggleWorldExtentVisibility(); + applyReflectionMaterial(worldExtent, scene); Sandcastle.highlight(applyReflectionMaterial); } })); @@ -697,8 +697,8 @@ baseMaterialMenu.addChild(new MenuItem({ label: 'Refraction', onClick: function() { - toggleWorldPolygonVisibility(); - applyRefractionMaterial(worldPolygon, scene); + toggleWorldExtentVisibility(); + applyRefractionMaterial(worldExtent, scene); Sandcastle.highlight(applyRefractionMaterial); } })); @@ -706,8 +706,8 @@ baseMaterialMenu.addChild(new MenuItem({ label: 'Specular Map', onClick: function() { - togglePolygonVisibility(); - applySpecularMapMaterial(polygon, scene); + toggleExtentVisibility(); + applySpecularMapMaterial(extent, scene); Sandcastle.highlight(applySpecularMapMaterial); } })); @@ -715,8 +715,8 @@ proceduralTextureMenu.addChild(new MenuItem({ label: 'Stripe', onClick: function() { - togglePolygonVisibility(); - applyStripeMaterial(polygon, scene); + toggleExtentVisibility(); + applyStripeMaterial(extent, scene); Sandcastle.highlight(applyStripeMaterial); } })); @@ -724,8 +724,8 @@ proceduralTextureMenu.addChild(new MenuItem({ label: 'TieDye', onClick: function() { - togglePolygonVisibility(); - applyTieDyeMaterial(polygon, scene); + toggleExtentVisibility(); + applyTieDyeMaterial(extent, scene); Sandcastle.highlight(applyTieDyeMaterial); } })); @@ -733,8 +733,8 @@ proceduralTextureMenu.addChild(new MenuItem({ label: 'Wood', onClick: function() { - togglePolygonVisibility(); - applyWoodMaterial(polygon, scene); + toggleExtentVisibility(); + applyWoodMaterial(extent, scene); Sandcastle.highlight(applyWoodMaterial); } })); @@ -742,8 +742,8 @@ miscMaterialMenu.addChild(new MenuItem({ label: 'Water', onClick: function() { - toggleWorldPolygonVisibility(); - applyWaterMaterial(worldPolygon, scene); + toggleWorldExtentVisibility(); + applyWaterMaterial(worldExtent, scene); Sandcastle.highlight(applyWaterMaterial); } })); @@ -751,8 +751,8 @@ miscMaterialMenu.addChild(new MenuItem({ label: 'Erosion', onClick: function() { - togglePolygonVisibility(); - applyErosionMaterial(polygon, scene); + toggleExtentVisibility(); + applyErosionMaterial(extent, scene); Sandcastle.highlight(applyErosionMaterial); } })); @@ -760,8 +760,8 @@ miscMaterialMenu.addChild(new MenuItem({ label: 'RimLighting', onClick: function() { - toggleWorldPolygonVisibility(); - applyRimLightingMaterial(worldPolygon, scene); + toggleWorldExtentVisibility(); + applyRimLightingMaterial(worldExtent, scene); Sandcastle.highlight(applyRimLightingMaterial); } })); @@ -835,22 +835,25 @@ var primitives = scene.getPrimitives(); var ellipsoid = widget.centralBody.getEllipsoid(); - polygon = new Cesium.Polygon(); - polygon.configureExtent(new Cesium.Extent( - Cesium.Math.toRadians(-120.0), - Cesium.Math.toRadians(20.0), - Cesium.Math.toRadians(-60.0), - Cesium.Math.toRadians(40.0))); - primitives.add(polygon); - - worldPolygon = new Cesium.Polygon(); - worldPolygon.configureExtent(new Cesium.Extent( - Cesium.Math.toRadians(-180.0), - Cesium.Math.toRadians(-90.0), - Cesium.Math.toRadians(180.0), - Cesium.Math.toRadians(90.0))); - worldPolygon.show = false; - primitives.add(worldPolygon); + extent = new Cesium.ExtentPrimitive({ + extent : new Cesium.Extent( + Cesium.Math.toRadians(-120.0), + Cesium.Math.toRadians(20.0), + Cesium.Math.toRadians(-60.0), + Cesium.Math.toRadians(40.0)) + }); + primitives.add(extent); + + worldExtent = new Cesium.Polygon(); + worldExtent = new Cesium.ExtentPrimitive({ + extent : new Cesium.Extent( + Cesium.Math.toRadians(-180.0), + Cesium.Math.toRadians(-90.0), + Cesium.Math.toRadians(180.0), + Cesium.Math.toRadians(90.0)), + show : false + }); + primitives.add(worldExtent); var polylines = new Cesium.PolylineCollection(); polyline = polylines.add({ From 93e84f878a867f35cca769ed184789e03426bed0 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Fri, 28 Jun 2013 17:27:01 -0400 Subject: [PATCH 275/306] Doc improvements --- Source/Core/ColorGeometryInstanceAttribute.js | 16 +++++++++++++++- Source/Core/GeometryInstance.js | 2 +- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/Source/Core/ColorGeometryInstanceAttribute.js b/Source/Core/ColorGeometryInstanceAttribute.js index 843384f3d8e6..935a5b442331 100644 --- a/Source/Core/ColorGeometryInstanceAttribute.js +++ b/Source/Core/ColorGeometryInstanceAttribute.js @@ -93,7 +93,21 @@ define([ }; /** - * DOC_TBA + * Creates a new {@link ColorGeometryInstanceAttribute} instance given the provided {@link Color}. + * + * @param {Color} color The color. + * + * @returns {ColorGeometryInstanceAttribute} The new {@link ColorGeometryInstanceAttribute} instance. + * + * @exception {DeveloperError} color is required. + * + * @example + * var instance = new GeometryInstance({ + * geometry : // ... + * attributes : { + * color : ColorGeometryInstanceAttribute.fromColor(Color.CORNFLOWERBLUE), + * } + * }); */ ColorGeometryInstanceAttribute.fromColor = function(color) { if (typeof color === 'undefined') { diff --git a/Source/Core/GeometryInstance.js b/Source/Core/GeometryInstance.js index d2219658e897..a8c7f1b46141 100644 --- a/Source/Core/GeometryInstance.js +++ b/Source/Core/GeometryInstance.js @@ -122,7 +122,7 @@ define([ result.geometry = Geometry.clone(this.geometry); // Looses type info, e.g., BoxGeometry to Geometry. result.modelMatrix = this.modelMatrix.clone(result.modelMatrix); - result.id = this.id; // Shadow copy + result.id = this.id; // Shallow copy var attributes = this.attributes; var newAttributes = {}; From 93137fbe8f429863c2bb10d23dc1ec245e7bf712 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Fri, 28 Jun 2013 17:29:41 -0400 Subject: [PATCH 276/306] Fix Picking and Polygons Sandcastle examples. --- Apps/Sandcastle/gallery/Picking.html | 7 +++---- Apps/Sandcastle/gallery/Polygons.html | 15 +++++++-------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/Apps/Sandcastle/gallery/Picking.html b/Apps/Sandcastle/gallery/Picking.html index 706ca1c89746..22885ba42041 100644 --- a/Apps/Sandcastle/gallery/Picking.html +++ b/Apps/Sandcastle/gallery/Picking.html @@ -267,8 +267,8 @@ this._ellipsoid = scene.getPrimitives().getCentralBody().getEllipsoid(); this._finishHandler = handler; this._mouseHandler = new Cesium.ScreenSpaceEventHandler(this._canvas); - this._poly = new Cesium.Polygon(); - this._scene.getPrimitives().add(this._poly); + this._extentPrimitive = new Cesium.ExtentPrimitive(); + this._scene.getPrimitives().add(this._extentPrimitive); }; DrawExtentHelper.prototype.enableInput = function() { @@ -315,8 +315,7 @@ }; DrawExtentHelper.prototype.setPolyPts = function(mn, mx) { - var e = this.getExtent(mn, mx); - this._poly.configureExtent(e); + this._extentPrimitive.extent = this.getExtent(mn, mx); }; DrawExtentHelper.prototype.setToDegrees = function(w, s, e, n) { diff --git a/Apps/Sandcastle/gallery/Polygons.html b/Apps/Sandcastle/gallery/Polygons.html index d05ff20b1ca5..3e6f19ca3ccb 100644 --- a/Apps/Sandcastle/gallery/Polygons.html +++ b/Apps/Sandcastle/gallery/Polygons.html @@ -40,14 +40,14 @@ ])); primitives.add(polygon); - polygon = new Cesium.Polygon(); + polygon = new Cesium.ExtentPrimitive(); Sandcastle.declare(polygon); - polygon.configureExtent(new Cesium.Extent( + polygon.extent = new Cesium.Extent( Cesium.Math.toRadians(-110.0), Cesium.Math.toRadians(0.0), Cesium.Math.toRadians(-90.0), - Cesium.Math.toRadians(20.0)), - 0.0, Cesium.Math.toRadians(45)); + Cesium.Math.toRadians(20.0)); + polygon.rotation = Cesium.Math.toRadians(45); polygon.material = Cesium.Material.fromType(scene.getContext(), Cesium.Material.ColorType); polygon.material.uniforms.color = {red: 1.0, green: 0.0, blue: 1.0, alpha: 0.75}; primitives.add(polygon); @@ -99,14 +99,13 @@ primitives.add(polygonHierarchy); // Create a polygon from an extent - var polygonExtent = new Cesium.Polygon(); + var polygonExtent = new Cesium.ExtentPrimitive(); Sandcastle.declare(polygonExtent); // For highlighting on mouseover in Sandcastle. - polygonExtent.configureExtent( - new Cesium.Extent( + polygonExtent.extent = new Cesium.Extent( Cesium.Math.toRadians(-180.0), Cesium.Math.toRadians(50.0), Cesium.Math.toRadians(180.0), - Cesium.Math.toRadians(90.0))); + Cesium.Math.toRadians(90.0)); primitives.add(polygonExtent); // Apply a material to a polygon From f85fde956950f6e9629d1b23ae6728b362f7aaee Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Fri, 28 Jun 2013 17:46:34 -0400 Subject: [PATCH 277/306] Add screenshot for Sandcastle example --- .../gallery/Geometry and Appearances.jpg | Bin 0 -> 67578 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Apps/Sandcastle/gallery/Geometry and Appearances.jpg diff --git a/Apps/Sandcastle/gallery/Geometry and Appearances.jpg b/Apps/Sandcastle/gallery/Geometry and Appearances.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9b2e98e760f206bd7a3ba1f3f76d91c043ff2647 GIT binary patch literal 67578 zcmb@s2Urx#(=R;Bl5@^UmmpEHi6?0>ptI;AW8! z0as8ke5|FZ1b?ImRsaCuFC#}sTQp(-u(Nk{)>4*de*Qv_8EX!}0B8Xs;10lIWa8o| z_xSN6;D1|A#sRP=02t-D?dyNb_Wxc%Vru4M0sxT5V70NSi-{eGs{jC6XX5DW3IG_l z{jqqsI^JSX2Y}oe6cEHYx7gx8xb7Ak{|Ep4i$_~a0pvjd05-mnk+TH=5Nv~VW_J?{ zupdHv5cAoaTG@kG62#IbmPV!^_60Gwot?ui{tDuI#{aD!i~oj=jEw*7)5yr;U;H0k zz?R^^53O7rZH>JC`tkqg$-E4H^KuizPFKryuZuvnwp;6l#YiNR)6vQkh zE()OSZ^uFt@wU{~{hQ~Jso6tC5QAQX_T1S)>mPng7x$DC}oo_;r zKhnq* zYA{wYhA|c~eq$gorv9OUE&t{NtN>FG|EI72)*hrk1-yYBuvas{<)6{eY0;(8CD0#% zXIbzNKo><9`=@SjyLS5@{I{$YU|XKQ`dDw7hh z3|heA9}d1Ez74+1f7<_-#+Ztj4>46Rl`uJ=;m}HG540Wn1KI?w1(>0&&^qW(X!9-p zTdsdbF#;*KR=KsX3!nyC(F}0=>zDmM@nYR0e}$<0P0r(fb8VIXs`qDHUQVk z=3gdm&hG!=L%+RX0Jz|qP7crji~tO{2UGo%1g4ylKvB{%^U3vS`69;v@dAIXfMf3=0eo zj4+I3j695Lj4tqgUcorQ#Kfe;WXF5}dix7ZYfK-^D9jAZGR!v2Vaz4WV=OEz8Z0g> zDJ)GaBP>^}FsxLpVysrI5v&y~6gD0<6Se@h61E<;J$5j5GIk+$3-$>18ukSaF%Bz^ zIF2TcDUKITEKUwi1I`f63eE*C2`)RX6s|U|HEs~@2i#KJF5Fq%Lp(gZyLe)FPw=ep z0`WfJeZ%X;TfjTRC&lN)SHORX?}i_PpO4>$KZSotKtRAoAWNV};7SlfP(aW@@P`0J zNJhv@2q!cp3?TeSSVK5MxJ!gX#7ZPbWI*IiluT4fG(@ybj6=*utUzo;>`(lWxSn`| z_?U!@gr7u{#EvA2q>$tX$vP<(DI2LGsVV6j(rnTW(j_t|8H`MU%!Dk2EQhR%Y=sHrZZU3q?l0UEJor3vJnlS2JPW*( zypMQ;d24xh@3Y+3yB~kQ=l(UHFrO`74&MwvDZeUzFnCJ*E+I3aOrc3(GGTS$x5D3ruS6b*IE$2uY&>9j@cKdeg9%Y`(Z`}uqP=1mV)9}E zVohRa;v(X%;uYe15A2~9e@67|<+Flkr@9Yy6Lb;J??3l@-v5I3h1H8XJuJOvdU<-s`ilBV`YSJmUxvLL zf5raF^VJUnS_4~yW;5 zPik*t-|4{U;OQ{z$mJO3h;R~jN^(Lvt2yVnKwMtA)VY#_LGDktdv2j_3+~eHAKg(N z&pawUNj&X6e|m9xMR=`wD|zSop!=BkeD}TM8|1s-C+GLsAL4K9|2+T}@Frj-P&x2x z5N?o7&_FO>a6<4=h;B&38-_Q5Z$z zd&l=K`Q2rdNmO4nfAojwn;7$$!B~;l%s9+A`?&FVnfR{>BnjRLONr`v;f}7%&g81<0LtQFMYFz4Nnq}JWkMbYO(&^J9(oZu?Ge$CHGfT4=vfgE# zf3o^C`C0jM%@?*W$=R6M?%At3&vJTlMRN=CX!G9XUFF;7Bfe^V?JRguP*6x;7+Zu^ z_sg>R!|h*Q?flZ;)uHZscvuZ@Sa;v6-SdwgtE4P0LNIck6MRW7~GSMf=is!|yX4 z&pXCCpL7m(sde>sD|L7D$n~`LO7%AV5dTr%C)!urFVbK0Q}}1~fbc-|pvYj&(1W46 zUt+%+h9!qvMr20XM<0%MkHN?Ke{1|69@iP4oOn5bm^7VSpR%3WpLU(7z$!kn&1?vLqO&dxZzc%$Z zSGF9tF1EvVNOsb9@9kFY$?p9`K1Z(XJMZ5dL>Ex{|Wymf4Z#zV+bH$765bt0pL*^0Azv(D~R#I>us2?EeoIt z3jTY5l-uHBE-3I9fZ#iWp$Y2d=8ypZuo?j1%K7HzBID-fDhG_arvRYM=|4HyEjK0@ z$A2QaML!0k0&lPXz1%DSfr_41pl<5w04G?34PZb>fm@CL(g{Kf#z6nkL={5!FV=$G z`wx53h_wzs(sSVU#Olj*-#v`=XNa6mdgLI1_vx4btqU{r_(f!u!4z%N*! z7|`2-iH;7%z`_KB0x)X8!p6hF!p6nM#Ka-M!NtSF$H&LQAs{5cCj=qhZ6~*Fp?|f- zz{AGG2A}i)m*u7nAi;)kLpq_5y8s#q1WE$A=>(WS%`m_q4J^0f-WCWN6dePU2$Tb4 zs3r!*heFXnVKLA_LqPn%dH|gSgY*u+946TlBdohll>T<2Zu+;C#R^h^IN?j0Q5g<{j1skq!$UO7aBMR=vcRULC`#I6(>Q* zxWkW0D)$7-$cgN(KoB;$eEjF~b{v?X7Lvl)c^H?HMQDL_|5mlXH2XhOEcpMEX8$Vo zUwTag_)rKqc~BBS2Drpen=5&aNy^ZRgI_0l14ykqt0fc~KNEYb5s-g3n;Rl=(81sm zoqzWD=g+4ura@Ko$S;8`4K*Y$o9ymLz+d%xa4n5aXPdM_25^D_68p_Fa(XpxN4_Xn{cYO=wrt`5r zuLiP4Rpsgk{G2>fW@qrsOScw%Uk(PVm6q>n=%{=s@F> zw+x66Xtce4GFeFkQTP0saL1x9A4}4qqB}||ZML1h_$W|7WWlRHyL)69sFxouiQaJX z*2#RoVui=l9KHr|V<_DJaH6;B+tuOw* zvvmMr*P9%yN^|*UQFg~Gq74JH{kL$+KQJ#7=;;)_-cn>2Doohi>r2G?xT_AT_I zS@fUBu~q7GV!}nQO1O&b9E8g_=!48VcJIyd(>tXvO=ncQ)KAf9@D*!#9(S=gW8&+4 zv81e-tX+beumsRYirJ_+i4Iy5gIo!s{CV2gdBaDaK&MJ4{3E@IAJ1&;=En zAD{;~!)ZB-i%rpwU<@cRu^ZrS_F+#_vWH~)CzGIcDJd&jId@`JT+K0I?R>wM6 zrcBnEOrp-aA{hPGm!Vj9gJyNo0}I>MfH0O|(IIHQFt;<_$IwCYHLTZ?QET~{dXY9! z?YQ@#)|azcSu~PsTd|**!bh+TPXjop#YB4+wx)xKuwQt-3UODO*YLdJ=v{qGhU~lCB&t~bgf@wBag}+9#?MI~N*g!fX9!}!fX3moCvKMm|xB)MUw&(0MPeSLGgIUoz z5=mW^N6P105oCOw_mCtc^a5|^d-$XeXQ4@AeTj`sSN2v~FC+usC4^Qe1O-jhBN&_2 z)vGuxrEz{lInY4a;{>J{o4q0G7lNtU0!-=l%nu9#Nn)DTYD-uP&@g8=sh#s_4A!y~ z+VVxu^ps}l>>uDq_rzZo)KIb{F=TTqtY_B>Ff74nEln)vV(5R}VVQAWZT>LU2H-bUg_KIH*6KO#z zRQTBT1x+odQ(L#_n$yzwR{<}rua7VSl9y?txs&4?LKd?liz&5UcVtS+#%F$|4 zJpmYSS`BMsG5V&Y&rZYGd;>^6?Mr3hpe?1T^({Dk3x$df8EQB^nH}`L8v#{2)@1hMSsX(k$B(n19-2$>>m(TYR}vO!OY>PzZ5BU-6qaF6Ag78EiOinL zR1_sHjjWV7Qpstk#hT9CbB9(m`z)v3wg7>Da_N$m@SNX1mP;l%u3U%3f;Bko+;t-} zEbS2T_->0yBBM>HX@pbMQl|JCd!&uhS8ZkLM{H^i)Pw$~22Dr1Qqe4Uq+NG(v^s+a zeu!?x$2!IK1U+*wImlCc_ae(^Rpd2%=+|L8V0!MF_o4Xlg>o9*Ds#it;tk-#@J;;i zsY+2kyhiNV3%Ti6URvV8{Joa}=VMYuuUgE_w3IZ)`ji&NYMP-e>U}INwL(4ByrjnrB zcGklFu#JY<4QuT1e6>j3euyRp(zXT_mA(Oboi=2*C(AifYo>$cqX6$3%tgOICJn6d zls>CP3-!o#2t=DckVx}M6j_#w#)li=v*NPS=T0*g8PBYbWwzco@-Ps!JbJKHH znJ!gK-fm4?-1$3ZV*~>SL{0n&cw{{Rde7<%zMu7NtLS6}F!90-!G-SfsPyo}4k`U^ zNhaK-V@Wixsl2Ar<}+G-DC_IqEPf^t%mXFtK^f@xey9@Gh3QcN$Ec#vL|yXI(eiVb3)&l?y}pI@>f1GqK5AY8 z8J4o3No4(ia?6CbywE_wsX$)^0e5r2wl{ughbY(N3n-fF@_n$cd18f3dDFsduPv9|{y~Ur-I%T`YvsJA7Ootgi5ILRahgxPCYybKJ3_ zFaDM6;P4L|+oDf*GTGrQS6ur_=D_jU(b=ok#Q(aeP>)_xE z=PeyiakPAZhmr1B^J$nS|2eG{4_o~W5UZ;k5F_JopUP8Te$*F&&(5zH2zQ1?$;ZBW-P$gVw-eTlaef(Ndj#Bf5WC3~dfl{STyIfUp)TUU@l*|s+ z4S;@tB0x^aCCqgALt7%vs=`($9yjgV{X86`=P+W8?4nl0Yh5E`8=cW67$~2*5qz@9deY;a@O@SB1uS&x*)p)14|!X+@wl%Mn^3Nor{}TPmMo<&GMqRNH$4oS zPjf8l1~@M)9U0*dG$r=Dm}E+lf&E02#YBi((B#97V6tW!I^Kw=pq?ia1yCUfc0{0Y z<2O;30Bq^1lc-%8PJy0aS=%+~#W$UAZG+wu<`-Og<&rqWyVH~X5JR|Zi(Xnn^k%;g z&hF6Qy0kM83LckL$QT7o+dQg6KFp-r-~DWpH}LtBjaV5kx(zo=dfq9s84fkgMKQ3T z?rSGzY@!g;6t$fA=tLBwqi}8 z$}TM0rdQ*O0<54XAARuNr{}a0eb`|EI?~U>j?2=S;z)6=??o{omCB|c zoS35wJ(gr*uW>7p?x8pb*~vFRr?;iUMD>jKNp#h-mJ;3)-sT|(jE{?JA<5b~&FLA( z8^349&des0S;_`}ur~{7sK6}g0-yHedMocxAl;cl4a6JXb#y-)ElrKCXf#8tvC`iF z#OU*U@!(iKi>5FDM0~W?CvL z)U9ms_)6tWmPYzR0lqbJw00^zQhu47MiT%022hPK<)~Nr;g2Pmey$5gU#I3Jvw9ha zx5Qq%a05)_3F0r(lecdjZFEsi+2l^5jQw9~zbRrni;yI4_B=Ydl=y}IC`=c!WUOC` zDR?C%BmRu;DM4Vd%b2O#ViIvBsc-F|^NScFThQS*HKk0gKh?v%ppRlz! zm>lt6=oa0-&BCk|yNB*^CezShUG7gD<$b!4uUVWLVs=R!Y8}tQh)SR!Rul||d@tCF z%@z7MN%yTMU64o!+}>t@OV{OE$YS@-WL<1!UDsc7B9ObE@69-vc*+3*g+_J$z*qsI z)ljux&A$_`}e-&VhM)ebo& zA`@v}$v|;T#EHB1Oq7V+(|Wy!-tssCP8Xx$EIL#$=()}5b%eLByH?$ZpP&A{T|?aE z+P~^Y$+Doak6-9F=P3Z+=bG{I86j!pZ(0tvBU43{z-}tspVUdSPVK!6u}>$E`8W?N z{8uW<6J%{I7-Bd@XIzYMp3K8Sdg%Qbk5)DL?!Q__T+Vd(+yI;(T^Tw~tvBk{U>@|Q ziF@;x99yY(8BJ4N4uaug(3yP(>n05oU(+xRKHWSbS zr)-%WG_Yk1Gh94Z#f6rViE21GAzE*|y&1;PH~IjX!$?!p!JSLR(&M5eb%eEYhTbf}bU#%^1raE$Pu{=*utmx=9IGiRrH-$P5CTlr;YD%q5o zkLXRlo@}XER~YPi#(R{{{i>zMKis(XetP$9pKCv6EIYM#+K~nN{M_DN^Sb5vVeC$&#IU!6*>UNXw3E~GthIyh_RyBuR z-(X7LEyVuli;5y%;~yw*asXTM*p4PisU`&6AE@Qpu)t@!mGaWV(W^YWatBv;Y@G-R zja}lbwkIrj#E(slWvQKlaRycPt|tsNe|(u0db?vLY6Q!Az;b{IM_-%R8WMii0NJZ9 z8Hvdw`n@8eMu@kJ-x;ST(+yx`DhQPFe4G5xzUXsPnf*gtI9 zyn|cj#E&T?pH&!OBs%O)u&N>Mi!Dh)yS-iFmHEj3nAn$hUj)&o^DzxY9WR}a%Mog#tQ* z$n+yg(fRk>u%7ZnAUo*W^X5 z?GMJ=(nbj?O!>|MNfP~YbVBm;J}co|34teTNU*1mF0hv~95F<^Ix^hhB0-5mfcv@( zQyW_Gh<&np<__( zzP)IMZdJ0TT``j(_PU*!YB8e=?mF|A2!3M^ilbfzqO(0&hQjM%MqbN|EUm|)I$S39 zN}w)z{$m3sONJ3EO;yPk+OsE`tBT7kmW3-StifM(zbC)sgRL6<`X;IOEsj(r`qXc( zu6Ji9CaXkRV*K6DK@*l8H-kDD)&}T(p9rUiP9pbh0Q>t3Gj(PyU07uru&>oJF$V0v zS0g1dv>rx2fCnq1J5~xD&1BJykjs9Br_VZi?TQjBDU$w1Dv~_2>SSw^o%TOYW58hs5+ablwUoZ1E2Gh$h z&73ET(Ytn0FkRA~acP3l6CaBHAiXlcfiz(E_1M=E9GSSJPAixyZe92Hd}^76o)U=_ z{W!C3IFx$Gp+t$?x5dC~E6qjzO`rL4(3?BK%jXxr&^0=KO1M;I{q*BFP+eC}JzOf2 z;=l`ihQ{Y(4~tj*<;Cki+z~Rk9pz_<*3oyrghXS^^~{qQ)6iK{?;R$U4(oHKkCqZa zmr_>cU(?KC)=^}$F<8eNsIlaeHi70JX6lnH&az9j-at@=8Rs%HdK{5;rdn*3Qsjbj z7H6D zj+KtTBzn3r(x5pdvvmKG(~yaxB`!DYYl~vL7=%ttNqUOK$G%jdLx#W?zO-tHQm7*E z(6@4)s{EF`kWqPP@>)zdg!Rov05_Qew+DZ{a(Dq@lqje60X8hxKh*Gk*nMoITb6+J z(B-vq5xg%XYC>VXY=&@?z(X~1cWSKM@d2SrR<7@+Q36Z6`O`SrK`|_rrL&1&H$VmZ zc2KGRcth#uJkQ3?6a$K3Asd-0MHilkrUbZP_|o&HPEkaHno|sgYQ4 zw$E@(n{{_SGq(|zcutRqQ(6(-_LC|ypy{<4t`WlT@*%AISt(rLHpXq7i_P1bmgs@NQ z&X zLb2VCy)<~tlktZRy7Ff2xNJTL>9Fl_A)Fkdv#(wjQH^Jm=GF?!C`a=y9P`VI5i0~|C*AD}I zEheY1m4_s2!o^mtisP$yE6U{nZ=v>**rofL%he`B?ymrX0L1hV$z}xA zj8F=+Z1By}VOj051B$Dxv;RQ1&43b#^_J&%i1LZLxXo4qa2C=OTS>DPe!z$6y%s)p z10b^JX(gXNNG$Y~|NTsk?6bab^=PN{8Y;B--W0;ly}@DUAD(@NLq(>zXz3EkLxHsHM>U@=ekg zig#65qSy|rM4g}C0G@BCrOp$F47f54V7f8y9mkdqXnW11EDRiWm4~V3k%}@w0Ysm| zG?_eafVMR4r^KXc1IFX%CL8tXgg!0nRS)MZ4|wR`iz_#SEzpEy_1tF%8oLX z&ahdv(I+W{SN+U;xl4T}*v%)4xB(IkBrfDU4;SBtW;X|5pj7)hlt;#rTVE*tto*vg zp0di&Tp@DuBlqpn_6*h2sZs5v&4eo%80{Gw6A__TU$%k94G@2hcLNX>U8UA6T~jIt zI{O6J=$l^C6;=;jl7bG_5IW`0ekmG$kK1?7eMA7DVJBcl5MGH-EZLpz+*$IIzbe%X z-$Nv|uFV#6N(TWH5nlTeooOKwhN!nM(_8-t81~Jy)Z5#vTdjF*p*F!3y3OGn)}1mY z-B)k}1Tj@KI9!srAgDS+99s!nSbQbM)24zSaSP9=C6e*=g-zX=R#}FQSM13kW@WHF z$HivaylWx~u|IU*0H*aZc2R(Y#)zY%Tu)tD?+}i!!@gnAVx|n(U1#6KzO=`*&fkF@N+!QgF_=|_ZwGKuOyZXH0`&OCEr}?|4S?|l zweZ=n-RA4%>+z$aFL@YQx|I$j`i}_3;$Aj>v;7J|b`pxBkCdh7q?c2RyS%bZ3kV&s z)Je}MSTv(ra~M)s-HVt<%4;&A6mx9+WVBwTuD`hf_zftQvQX>~IyKRXx7a>PaG_BP zv6%W~`XH_;F5(wtP+YOy;k;kKHyDZ8z6|^BS<(}6Ra7EW7)qWII_?FwQF}b2PcNQXzZpir+~e5$dKqdpR+e~I#=SoTJ3g) z+2LyU_0Py_> zHyBV20m_CvPxhl+rIcLSx3c=Tg2y4NN*CIhN~`g?)1usMWa;#dPD8%#MS^-><4EoV zC0Y%b(x9UzjKR+(rtZscf>BKO$6X=!F~C$8O(Y%ZGP=L>c%T*ZiRlU@BJ_|62CsDu z{7Cn%U6#%g3Yzw{bG_Xr|Y zVB?F)zvn~IO~q`tmJgeV%7=gON~HfL@jN7i%{%DII@FYP&6Jcs#W7$b=;Nu=$0OhFtrPUAgP` zq)K;fGBPb)g6fQv7tX*JD6$pG^q)luJDiK?ncCbg4<8Yy(oxPtJXR5Hqef5nr{Ls4O)c!J4P zMrI;`ki;L|fHdOxa$hxPl2g+mLQ8h;+9*9x1s3vS+1vb63{B}>-{irOZSAXF&BxN! z+#X-12Y{Fdw&WeWE|~$OkZbMs+3SV?#H2(@6BuyN`VuD?t35cmjgm|-bGH-)uL*qP zbHN&_O9CtE^6n;qfNd~W_@sP5!WH(zKLfx*_jZ!4qYJtFsV}shCYy_<`**i9&d#|O zr>l8402ABv`wF28_oRmHnO=;pnY}0d@Pi$I#J0KT=-33l6QOdt80Ze5Rr&IGh6UpT zlF*YW8epL@KSK+~8ybj0N69 zGj-r3bXJRPY%FWxq)Cs;#I3EBp2~+c2A03&3FZ?U^pnBem1gvX?BDNvH>NH!qNChK z*z4gB1nA8Zg%-U_VWqB@fr%#>DY~dn(aX%dbLRHEH=Z6;E!kYnxo^I1T@9qqg+M*iz5TT4wW zwhylVj6iXL^1dW(le%h>4!w|6PU4K);en*!N&i)&FPPVqmu4f%rm_`(Ni$j|Q%2an z{`JMuG(_X^!#I6JXt*77!Y78$fszw_GDx^4ie0g6XKg8fblS?>Hf&GsfY;vQIZi}^ zRv%Q9n&`t2`f^l!Mn04O^{$xxY%} zrE(R9wl)N-Yb7=92Y-y~NRdrWi5u^Hw)8~AA-xQVkrBSYd-IWz>8`!pGXH|BwL<@? zETo15-gUbSq{OWmuTz|&He$yC7PF=FAiiYhcXrv}2BAl7vK|#XH7ui_J!3D#DAvrEVVM82+e>yH!dve z9_-1RZ;GwERJ4fZ=$As)%q8V?8DcWU^Xs+7PhF?<_iEm*)cq{ONbKJ_-qcHX{g_qK z=rJ-rd+~8m=8^)ss2k0bTT?qxa>;JHkyM4;#<8sDBsX5D)!_fJs8Q@k&XVQwA}!#p?WI~C6>Ku2!x z@6l(~O${^w$c$O*lvtxLR>M*VHl<`Z)v5uXj?1qDu^xqO%dzSm`QO>qHZ(@gOQ-R7 z`19+HPJNu>^#ms^kzSFe=Jm+}k^POQ0Xwe~GsQExIGSXnx)K%hRs07#1>vkSMEr+| z2TXb1#+6BmbT}OLe{$iMuSbn|9e7!0XP#)0e*N=d2pW~?DSBz$lFAU%SkNP!R8{M- z`{$7r+wT}YD%OcroJP?f%w+N74eBt}vFiIGTnx_+xZYXTdKE#;-w=x$x7~Zy9K00c zO}oOa<**aM^gL~O-cae06P7Wut2VmsJ7Sk0&J(c~HDO2n-O0J7M_8Fvw0q{b_3Ww# z?qwsDT#Iw@>JrsUiC7!3J(y7<6vuaz5nmUoZTg_`rRQ{n_e5ps-UIr>MrxjRdVjGp z%+YI-&3SBTmYzkrXeFU;Bk7EwYDaC~6T3yqmrfm-$%<{$=D&4I5qWAF;#mY|g}AH%jse^k&v@24eO}>u*?mb{W#J{6z;b-#Jo${1sH{wbE50Oc_Gm2KAYZw} zQkrhO`s2sOSJ3a`uW~ymMQTpM%e$_7@rj_Y0x9otx4rEliw`oRnhwQUGBkQX_+}lYla_B?&Zs52zkSHO^|yi-$R_| z`xBhHu=E4bjbkZ|l*M(2odnB0$#@Y3Ea#_;h5U(wGUCTyod`veV?2)4uIUf9%&0jl zMnwE|l{-?hD%im^W^rCUczxz`{2N_PoF@~Owx$<^HbX)$mTJcqZ3^;hbYALI>2MJ{J1Rhn#;d?TrX>;+79>o_3kDjRkB2S zf!GuvBpC~aV}$oEr=3*nvYw2%?yGZckJQe4IHWGG(%k*>9y#GRegh=bFH19_=9cW} zo(1`G1(cv72fk@Z%;?7F(zHQB1W)LTaL;QO)*^)Qb{PA$Tgu0TBzl7M7CFp_Rx*|5 z<3eK1d$7<6ZIht@tVvn5MXqWoyY?Y(0X>iQa*7; zflpK1&Ar1eAu4q%@%T$FN&Kif#Il8y&qSH$v!y37>pfn@mg?ao%TFC(<_hUaNza)X zXI!?FBky?S^L!a%G5YzWP~Yh_C*CbUQW9PfQ9dCg8*6c@wLhnYG-DxmNf zC^#kugPlTOQq)^|J%>wjB1BKPG_}D?@`&m=8l~nhVv<6|!<+-uyRe6;fxSOqS?L!0 zNxyR(6^pxwSRTH3+s}u9q%SiznU1=aNDnDb=&h=?ZqFD;spoEUIhnX+swPPSF6)?@ z($%|Wmrr8a)iOy(FUpc`fRsO31*?k!wo-29)rS+;M6<(3HLYMQ@g7BU;ek?GGrW4& zWVfJ6qqk$i;_cQaJWzl|ojJSsT$8IaG9N#mnmKD|etP~I8*gzabm9S-<+)j3vFSI< z_d(~nFZN+4UdXw}Z1WRtXMf9H#I^r#Gi7EUz7fCWD6H zah2JDk4)QvSzy=7&_^PXltH!2iPFXU?o^l}9dUrWoT0BjTGQYv zj9^$lZePO?pJj+z$~!=&ul373)coj1teI z+0C#77VgnUX`s;}V`oCH3H~&V+L@1CVp*q*JLhNM*C50j;*-pb#z=y(ORSN9@c1Wq zOZsJ&Gh>&}ui4F+!Z)8(bSr4C>XmKn%8=m~F%Ah&HW2r^#I-c0P)o^ejY?TlFaIe` zga?06Y3GT{NpKGtt?%~E@;-Hl&HAPsTu7yBXE3IQ1iiJqALmN=;KB|#>4!6sCv znVBCSM6(=A-w}}NDb`kd><=c%2e|}0qUr`dAs1+4E`GiMn|Mgr7S;v7> z$6qrfz~c7owX9t+_Ad4kESNvgx=PwWVYa@H!ziggc?d69Ie#H>yyQgz*~d?fKiPdE zG`vkRHM~SmPYZvDHN?N^7zk+caI-x>Pi!9mBDR0oCa9>sF8%&8sC>{HKP1Z3qsLIS ztUnBVId3eU9z7p^S=dqb{svgzuQ`=9`3{hqWY$v;I?ez2ROc4o^gc=T?(6ic!wKqL zXLSt0^G)zAmLXgQsX!Do(}qsq=`F3s&3UonU0von(uu| zJVP_7e)H}yfcyMujijw$oHm-uCP&d7&e^Qy%qH`^n2mU|=YeRBPf}<^dtt|Dfiyy- zXvLl7DZA;*we07SI!TfVZ|dxS5*Zrb!x@xY@Qzv9dPNl?O=&$(?1numTNB3}CE%Ws zy|Hy%VmX|7SCxFp{en!aJ8dlX4qB8j&>{(Xbj?9%5qJ#+-{9szy97^rpC)aL{A(b4F z;gd1G0Z@0Z8}}*C$JL?*Jm#Ys^VI$Gec8ZO+`#wVRirPD&0@fGt--J)fBw7Jht+FIm@i-`#3-*L)>%tXD_5E$@8wb9xq zw~>0-b=K0mVbUK+8x6Mzp@IWw<~++5D{V3#pn?jBn5_+%dAyv^7Q%IO>Fy}5kuYOt z$AnM}rS50av4wn29(}ywUUvV$@SWuJ3xAkkLME?==9igkqLo#@fu%hZm%|%>%A7y+ zS233)6xEx|IE7oA<>L6xi<72G;>4!L0nOB9;r=4mW75)BxsqDusIJ8fg-*ff8E8wt z+G~B59IH@8tT+lCB~OFjy|^O;;YCyLC?&S0S%W1}1i%(YL(+0IGl1{zPdyzH# zN$9U@q&LK9m=6ukkj6vTWCKs`)1noIRyF{=gx*SqoT7U_RvTg?nJRQcE^SKG%TROG zaABSxwn)5C!>VuSyl_c+I|gO6mWht*2fhrt#B+;(SE@do#3Z&-JezX6&3i-bK z;3b7F<#A*Qp@HYU3zah^P3?@`?eX$=>%K*x52m6fr<+s4o9--a)aYAnPUmK3yUuez z+KXT|7duOhh*#F~9UY=La_DBFdcKkD?p+qPH?m2m>uE1-l8}Hw*A82S#CyL6rg~nw z%2b|ifAp|g*eXLk%|yQ*9N8<)OR!0FTa_I2-?uP-)e|TEGALNEOELH5q-Uyqit^iQ zQkCM}oKbVWq~u|I`(c$lCBNw4Vrkha=&!?luM)%JMfQk%^{?>V-(_pldwx@Ah9qFl zu&>(nnqy2|^;FM=-H-L&+|-=Ge8gev_ttlUo+c-0Zy#1Sxs6I1qECj?f2|LtH8aY@ ze8T#4E9s~#yR>tD3fFat=khm=WiHP>lk0wPgCG)_MSRJK^k@%=w&;AbRTN<4z)~Y3 zpi!Z(hokUtfCiU-#kY&@Lm>49$u<+Aq>k0n9PXdP?-d;ZHXQ629^9Urr8oew96H(7 zcvGs$J>4Qs*ZF4hverw%kr_rRBCY56GAABYS{YIdWt-JLml4$^N{8ApWMXi87~MlT zS)7lZ(bIqb4DCty}Yj`LhREaJ2?Y9E}N zGH}@%NzI>qVU@{M5kMiCpw})g`AdGgL{hGzkH&w46MM*Z;uR-Jx>SBu zNG@(n!e_CwQhk|AT$R?mjW0`@@ZE=ck+T7Xo@H=F(e)XCCF||i2i?ar5-?to-pCF#L$BYU^j#I{{-(NT>aQr0FHog4WOERl*ye=RjO{soq zh-@CdAVZ@0$#P_ya@uB!b)ouk_R8VxTZfPA`7|f_Dcz!x(Hez0B~52(emuKM;0qg; zrXfxCH-dUGF}%EQv|5GLpIQ~MZfCqOEG<{<_nDGpiWq-3Y?;jGX#r2^q;l6#iFntf zqC%5meRT;qr6aOj3|zq76#Y@j=hLRr)Z>yHEjm$pbrFtochcF!`4FxHZvKMEy>Q?A zQf1SUb}W^Bf7BcFEr&7PC4V4^Z@OH`32zxLD;t`;&bO4*^>XvN$|{_k zo!+|>S;_5;fnW%+T0?iqys{Sal^pl3ZqlWy9j>x=k9g`CE6Q~k=!0+>P;)}g7&QMs z0PR2$ztckNzBLmIT!_+5E-BeF=*KuekMgct$6i0uz7yE9{7>;I)NZ$Kg=CLy)WZNO zM*~wd;DcDZl+BLpeQQZTr1axuknzY?_H7u@KAZ-g;um)CN$ zOMKdl#K_q^Z6tt6EX0sN+s~^?6&?K@V2jMcAq2@Ur3Ni7zAe!nA{Eq zI@Sh}`$GId{h%%`C(?W~uRI1ET--yc{{Uy%LW*;_onuJQj-`ehis#F+Y2sn+u{GgE zCvIAt&AqkvBPDNHC#Kf3byl7m;irj<`BYz=52N)B7VhTX&9T&DYvKSuV||Oex!<2$ z0qdNT#ZuDr-B&=?n(Aw{j>dUWC5hdoVT^8Y%^)GT_ZhE*yk+7Tv~Lz%;!D?)aV+ra zQ%$!gmEPbN`tl8WKfsUMLO+JKa$0z`bt~H;^VH!B;KP_kV|$rvY~1A+RQ^7Cw?`!1rV z^@?>H{zl!sZy5ZJ`usYm+u38N%}e=a{{Z&r#PkmnYgXE=^tPJij-9A1cxc}0KeWdl zI^meGQ`ixX-%9GVJy%EZ4ugGlqG{H1+(N=I%r@?EfH1rkImqe7LGVXO@U7>=$o~N0 zZtC}%XNWFjlkIl)c4F$*JV;6vZNZyzZ6rQUN$e}p`~mRC;eNNRm9g>dwXXCh?Dv{H zqB%Q|Gaw3j9I4M7S0*Bqu()|*CpfsJdnqYPTWti~pQ4L6Wsufi4C%l7i%mbqNb?^F z_?J}Cb$>ERpb%Usj#!!zEKzbckn76yKX@K1(|i%G-N)hAy|mOGSSOSZDmRKnQI1F) zH%t-r>0Q5!z7O~Y4-QNJ00{4kV;9znBv@HxMVu}^K&-rEcLetBocTSUfGzZQzYuB~ zB(HXI&osLvKrw-jW0Bj8R(U=iws{#;!NT!Q&i>=Sr1@L*Nu!GsMtN+MD@kgvqf%dd zTSb_@CTcntiM4A~(sX;fDEzj!x|(N^*Bi;&Q3|kImcSx zhv9yyc{|?R+f8tiA=q-07hq3pj04EXtdbU@M@AZye`kD`Gy!|hEs-8zsDO62g{5eGmgfrXtq&XV#`%Xr1IF1w=e>vbj}8T zz5C;elGEY$jHO7mt4|JV3t_NBacvcwNr0rO-eN2RVY9hdkTG1}$6ttc9}BImPP?UQ za?N%{wY|E={{U-}OlOSXw_f{s7zCbc&h}L&QBmc5{kr_lnw;2be%7p7UTVg7#IJ)M zANaMV7_RhP3ClXHw~|}CPi&)uvEy)D`T|Ek!a>DJ@IUr}{h&YKocFJ1`zLtayhY$N zK5zUZo+5}}=;xfW2#e<2lhnf`EW^3$UPY()yWSq-MKwC-`o@ zRy;Y^!eaHDTwi-z{sZ~k`>)~O{1lh=ZvDL_UkLu$o*Ewlz9L*Ow-V|t=V&*woB&e$ zYW6A;%jROb$^F;(P|of!g=sdZHGw_hE+39y5 z0{mK@F8E=oI4|L?Xg)LtYf5Ah4;D%c7!mUQ~>p|1yF)1vpiN!om4dHV{>Sc1Y z`qP&G051OkBiO<54Cpma8yz0fTR-dXKPhgC8-FUsLR_D?$af||<301AZ_b-_Wc#J_ zTV~uiQ;@*({LX8!_<`_aSNLJB$sdX>9ekD~JH|@!lgKBzJm$HWq1$dFMJ728c7cNV zK7+4O)Qb43_k`HZEtCXj1D<&Q0DByDs=`IwJhWf| z!+?9|oM2#QIPY6mVPqLl&Lcp?Dgm?-21x18)6mvjw}8bjlM*U3XXVCDcCh3)NcOD^;Tz{2 zum}g&-xS0>qcOl%MpKs?xX1&qAK_9!e#^R08_XMnAXBvg931DbUOIH^RfWS1$p9sr zvh*W4>5h74tc^)!noY{UF(-2!$EGq#!0H#UpaxyU_g3NEFpL<7+sVK^ao3*pCXWa&kWk*LQ001-DcMSeyj_gWo3^H8Lpvxxe7pNX%dGLr;O~!x$Rw zJ;(O`rGxm48Yw^E*b?Xd2xss-+zdJX-XwqA!KqPHiD&W$CM60&1?*3)ThMgLb*t|u zPmW0?+wufW!H-~h7#{W1{4V$_s{Bp7jyoG^gl@wRgOlrl@5eRzN&f%@{{a60fT-R#y6-jxA%fw1GU?WS9g<)C`hI-~a*V+P&AsdN;r? z_#>CXYi|&K)OwY%@deGXpGolDnylKkvdVFYVI*x$+!Vr!c_xGw%8+8do(L=xNRx!Pk=G9|fe;w10$ z5uTVi#eF9SgZw?@HF*3jK3(9<9S1tpKkuIcl~T~9}4~jT;9c{!+jml(XF<5FEmlBki8l- zB?!+^BXsTl*SC24z`6&7J|4{?TFrZIi}N9J9!!yiBwzv4ryPCUSDyIi#WVf3L*prC zvat#wNNuM8-32%yh#xu(9v5nyXKh0tg!NyF7Ew#4wd5L7O&mdd-InmVDyrCDyue_0 zzz30$Ukf^~5ZtEqK9-FoP7V~KW^*_CVqEGm$#dmc!XyfVZor4MX`j5qzf;tl44UY* zPYPf7`fVppu+#4(`ydi57PjcAX$dQtC47Z0!w2tV?di0N?CpFL;co%x@!t59PpUjq zGr<+Zw#)?qL$Ze4rwrRcP+0PXsLY-nT|&wWq%7%a6US=jBjzkVQ z00HMb)+$LmBUoX5jBPzx-RQb*wLY0=Wnrt`X^@Eu$0fb2N}?qJPz>YdCvoH0_rUCY zOW^xdwu3sA-k@#Q&1+PVV^T*}b&Vu*pM9g$`s4fq@MKz)5^A0}vvDkZ@T}c_a{duMPhIf@x}g zFYrHw{8^-G*6SXFCEji0niC|SZA_%TQuN!kR5Kpvxc(~oJ5l&wWue>z)GcC`?l#J} zU?Yo;MhQ9Rk6r~eyk9SdbyrZfQL5xLO28KBfHFsOz+Sz2@_kHJZ0pcer5$wF{E_qd zZbb~5rAm~VN^bfsZu`EckABs*_nNMi2Z?mpZXfJ1wZ5W-G3CNe<&X|C6^m}hcwl-0 zYtDaQuNK~Fe-J!np;=5@OIYC4RBQ~fO3cW^J-4c<$Ne)t_4YGa>V708E-gH;i@Buo zvO?qTw)H+Hqq^52i&9&Y?C;}z0833UehMG@RNgg)sGGO9@9XyfaV+PKYU z_L}i=+a0C-yjWeOg`9amT!ZUd{{XV5!)q^y9zDI*z9n1Bs%d(2nO-ys4ARNMsRsa$ zyzE9#0Arf>?;3n4@MW^IY5p0|*^2H79g@g)`;s^#`d6nnOAM5GZqG$hNjWPYCLh{= z$8kPk);7Txb7=?6M_@KqwV&-hb7w)EJ(p`lO+B%cJJZ0hSu9Lcy~r811h?7K$g#8wxwceFR}R<%KD?qe`F7f zciuJlv#444*7+`;_R>p)Ge(HMWNi>CHlQ1^GLzSgSGD+u;oKUvy~|kMTw7`^aTLk} z3w-xPDnaN5Sxs_-!dgC);`?n=NYgZn8^~-^%ZlDOQb>fb#gN7&9nwNcB=3?$Co$oA zts3^{#1{tE;Dv005J*(x)SM30o+p*m(O6b*bU|^WO$Cd`V{k6+A;D=|1n%GtgCoDD zG3{AbUK!RjO=c^Fhfe!#&+iQ36EbudJp9K1bv-d&p>yE`)Aacbg#Q3$yP7k+$Owi` zgeh&=B>VAPRqnHWeG6J#yf9B0+P+BzRFC2WWHx$pS-mzhlahR`9(S#H63W|BZDUOE z_lE|tGyd}BH2A#o`Q(QKBk(z`D<2T*(Ci)}E+Y%DDxISq;~eAGyXbsJbaeYm9d6n< zeA9t*4i3ZIoaA%K#|E=?_;mQ}=e^V-y3}p7{J1e8cL908MZsd&JYuEJQb`f)n)i|A zUmY}W18bfQ`*+6uKTf>UY)Ek{#~`0^=!j5rOz>x%bqbQjefYO|Lr z=$ltLrtdVBu6lRu>#X>5#U3WQ@khg-hc{MV*%`AD>36WK7b-~rl_dnEXRbNpo|Jgo z_NcJZd`4{iMd58vM0X)}>afjfU4{X5XwpStob=<|*SUCiPLsfzP#zAlwzSh4;p9tl za9Ly}j>W-M8;cxq>F-?6$1P*+e+{)I@lTZ|mdaw4NgITOWC*tc8SnwX&-igu#L=x= zmD6oK7Ok^MN0Ke`9DjknCHP0hFwG>=+RX6${{Uu-QbO&5I13;~$0wX)8RsMe(|kJk zsqp^*;=ZWX{uR3x_t3=6_Cq7Y(iP+tF1RNHkfib0jMv0>{uI~zEoW_W;_Vky(=D$- zYk98iB!o@}bSybPO84)8zp};G$4`U{;){!jv^(f788qv=SaCJfakd$yiFT=A#{t0% zan5mG#w#qs;i2s%Hlp;u^?Q*@wC3!U&#rtS;4`Ud27PWqw=v0q99Jzcc)%N5m0hHA zF;VI|J)Wy+HMDm2_iSvwu;$nY(bm$ zGlCy(8$AIh{p#wP>s|8JXkbT;luAUBqP%$@#tGnzk&O1Qm#Jt?r7QWP(2Tj_v@b!X z!)*YISB_ZHHTk|=xjg~SdB=Zh&(kbg3+axHJh6RTkT~t%--^+&lU|bU89YVhO$2f7 z@`lhAJC49(Ju}5$x$%CJaiPqX+FhK|z*U&B+KRkn9uLiocR9~)DHDH zOaA~D+AL$j-YnO2uQ|8d!wu7fxY_}7BL@wRGH^$!u7Bdqp1biMSkv_%h?=8o0>as? zBMeGR32@un9Y7n09owFQxBM0Hn!`u9ylXh6y10@DQEJShEx0GkjY!Dk40G47widh} zS_^cy60mhyAZURb(11ok#~V*y(u%L!MaH7$PkZb6{szBXtm&$L)?B^0owV{e4-$M4 zu<_&C$!p>-6zGzSMg^XwTRby>c9&cu zwRJj55t6(2S1Z@0mX_^gw>La@`yluS;-7_K)I0&GjXM7R0XNyBe#;;5S?`Je0J09x0RI5NKr~%f;@`uhCKzun9cI_G*uXs7UC2V-C;c;> z!wvwE0`0Gw{7w5TU+KOC({-h2JS*Z2J|i9GCsAv1S9g~x%#K8E!9tP1ErZ7FpDu^v zMz4RQ+-cr7yq{gPa?(b(ujd%1B!2UIeBFpRVZlDtwpmuQyr|apiZ9Yj%}HMW0Ditl z7BAVuNz>$S=NIa_euwLS#?SaCzrp_i_$eR3iT)z~#5(So;*BC!Xy=XvG2LnNVu`q!;hr`IE4y}O4Yox%WmAC4tzWBuv&Zex@K62< z^Wm7hA@T0ZMfh*=j_CO?S-Ta|_4g+W_8H_SY=o5`XOXv(z#*6B+xCB6!{)Tr9MV3O zEom?Df0{V3xQf|)?}c|?%YFX2k*z2)AMr%B}_Gb5rNpM`#7_}Agaq44VR z?$gAOyfPylju#t&z#yDwx38^ywsFJN@|VuN>Q8AckFv|NdO3`J*J*V}IMEq4yOk&J zA{?E*pbT^C^rR~AJTb~VxfRY!akoECl^@zRJ|YFTHb1&a^dGP1Ma|!wrbHWD9KOSV z4{iqo{{XFC0qP8Gx3?>hz+(jCan3o%Joh})Vwk|mw?8Q(o70A zkievboNxvY;ZQOJsjb|X613h+(KjXHz=a0k2r?Q;VmuIKlef~$K z45t}Vimy(Slsm0{`(EEO`mX-~gJ9c#{1DgRgJTKS z5`yw6A(kfB)uWM0vLExejI+onlatLe2BXT9b7@cS1j9 zf9>7hk@>|8D^pT$o}=s0dViSxUsUn;?T_($Qt=0mbxl{rJ|))YYn?+>zL3b-B(Ws) zL>%o!0aO600039j{{XWG?8_H`qqKhuSbeitx{*@jUb%}f>1uP60-me}eslN?;Etz4 z_$e2{%^EEyL$emvjK8~%IEZ`MK+o?pmMAfjSo(2*E7d$Je|6x`4Z~xqN0+)!m+bG5 z7@kgBsmQ{pQ;s-nSLFG}5mm?DjTOsJ@qWHuUzzopUQr5i_PB?6eqYyep1<(gO%CEq z4-8&Q4Val^o?kebuXkrM$hiIEk&az}P{0Kl$<^>5!|~y*2JcbQ?5(dHscElf3oAKX zf#u+G1{r={Gn(eUCTjNn7SWc{EBWHT)QD@lAl)mUinL$-FhaxCESypavno z41>=c@%|;(PLJW(ZicH5+2>}DbQq9)zrd`dkFE}Lj(b&~haU#@4~SN`*IpxdEUjP4 z#8Sz%x&yhBfYKafFF463l4_!-A9tzE8m+!cOJ1(`DR`IS_NC*!I_f<_)$X+EqQQq^ zysD~q2P6-dJba$tTFdxFZQ;#oX>`fn?@|%l$2y2^e3;c_Q<%;{0au)!E7|NkKc{K1 z+-ZIZ`yxRbEK;O^8Rjm>1fIFt8L&bn8gv$Z7V##dZ#jTHv{rV>BvB0G8^Qow z^MY~fjCJPx8?I?uKCN-5_zwMr%DG#K-M7ypWQHzw{JHOw*kjw!^mov;pNiKSW}gMr z>!Xi8c;l7Y6l?*8m6wmaI3%7jJJ%25y*o&_@y+I^W2e}}ueo7ZP~nDf8ytdgxcvVB z1vxdlDr!k{M#H>CHMPCELb1%(4~8xdQAb}>=~OLsO*-#YwbX6H-fEV>Bv7n>Bt&|W zI5`}BeQQGFQL|eyX1YULDN?b@l58QnlaP7*I}Rz@R+Aoua}4^VQh9JVb&-@0D0L;+ zb>sYs$<4^d)hbJt`W;=qxvguubIszr>x(mxA-ABUD<&%^Hs zMer-(R*Rwd#=_H1+BGT5?N`taIqOvEv3nh zcu52{$3<)rRCKQgc(Yd2;e88E*KVU$62W)>00_PJ*(3v$m1bqxBxi=ok{Nn+%|~zI zO;PS6)ASqf5a~8>N45)HA5x!3vWziiVz#ytMG9q$F(CmYl5$RJmW}o%c?PSXcvDfh zXK5yzQSkkZ_1w-_mU*sjAbDnTNhRIciR6<>RKxC~{{XL-Q6vPpYx zrYozNndLG%k`7CNat?Ap0o**DWF+*y54V%-p)aK~5;DIg54SZW;t4NW=H}iItarKH z{{Vep4l1Mgf);q-vmhwrB;&V!eE_a%jml0&-qO+3>K^`92hBnPuLXw#ALp%c{v(EQ ztHCsJ&u`?15;z<9KG_5h!_u_{)Q-hvaj>a4nBh-u2qV|ltXtjMTSFWg^|j^HfCoNO zl^k+G1-g5VzV$0n$tkO?8A?48JBZ>2_A7{61cd+*^dY#XYBMdBvHJu{0OLE!`MaDR zfBkfy*y|kf&lFNx#W2dC$;L8weNS4o6l*q@AD6mhBO$h)efoPI)r7s>1mfD*_`CiJ zLvGXf*TNFVf45Ga(sWyMf+Lw^8{3cX28@5eYnJ_rJbQQW`{O;9m!!@f!^Dy-7f}vJ z87loc1DyJTeXHru+Q0T^v-tVoSXV`o+Q(MYrQc_JF5$2@`pDgV2@A;RM@r^@Wq;V> z&){~pb$=P^HhR{%I(c^G6A;>S$rL~M%Eo(ZS%mS&J*v!&D9H0ZVovT) zKnHAAz1@w4rJIH*(y{q}+4LCg^%cxNgr?Q+WVvWes-q!e8<#z@Kf=CoHxGpBnrq!@ zGnW0JygzI4$Ka-^rfb&`Tf0n+YkP7+EH@bG4G!m8Gy5RRMB00657l^{;CUL+cb3Csimn zcXqD5I-Jg=Y0h5j=IN%NdG^KM#19N*m zg6ADTmCrqTh4rtYyan*f!hZmuc)lNK@x^g)gh>AY>m`0TF71{ebH+fZbuic!B|>ge z?`3brKfq3-sqrf>R(TG$`w4jNEh6ea3H(sJI#u}c?_#}qQaJ$wsPh;Sa5>}aUbXu@ zd>7aL0Q@<93&k3gej-6S$ZaGb#R$hLh0bw|9^DQrsIk`Oj>_6=>6w!xor{$`boBfU zL_A>&JciEotp@x1wL6adg(HHS;b_@Wx5+ne@m!*umV3 z9D&&ebJTO6rEE2=?0Otm8k|eI+xH|G%E_~+FYni%YQeVgCDo+L+E0-*LAUJ^o(VY} zKJQxJ(tJrLh+cT+Wtt3bVvJkLZ18e_8sk>j+R5y5m#-kYf3Psa^YgLbb;^t%%DhAN zoc*Bn4~JUBS{8u{rNdiAarUHP89ZMSG^VqdW^F)~}On<&deu$h|S1 z$2j~e$^QUpPk~MGheWr(@Zq$BTCi6^9HVTvhz8*pY=ANI9FThQM>Xr@wJ@s}1&dzq z>(c&54n0cN5VYvCm#QlY#Sox#3Iy01eEkuiDLQ&z-(v72S@w$mbkY z0~R`9{cH5RW><#Hu*#0nTR8MSK8`xJ7O%8=%dO8w__6y!_>;vtmHwY^s~_ytm7-U+ zUntz5BnD>t-!Q==f$d&y(Gn^>LilNxFEpWwpy;Ei?O0FaiMH_^L%Hf}w+)7+gom@G z8!ybpwOW{&bIsq>*VOfxv@31*jg0WC+@ETTMDdlq`=%r|*9h5Pn*uQ%2Hs{{V$Q@Kbp1yi?$d zjh0$pjZA-N)U+^mBBl8I*EZ@mF_dnddE!xko!|TvpZ*BvqxkQ_3*#?=GwGfq@aD5_ zFKjg(E@Zp3y@kf*k||>)Btkh1q=VYO8T3ybn|pI>tsuCyZUzVpybbe3#&xk*0KiR8W_$lH!lJ?ed3{G>w%6j#$G)N?sWGJCR zk1>@003SFQ9@*_*(iiPZ`w#ps{{VuFe$UDAWA-i8EWA(QtxU+CWDzuTTF#&AAf6Wi z;gxbSjse3f467+Wh(EQ5>}#%k2k}kX{f#TgNeI{3(due@N6uD|I#QE66X0P76wLyLetseMt2+ z?_aae?2%*fli};@8qT$UXw%%u91&ZED;Q1#K5|Lq^v4+In&&@fuZa2%lc_`D{{V|N z8eR6AE(NXS&8%`Ylb%AekbXi>U*SCPGmo`DX5R#OS45uULbtMx${Xno#lMpyD*3np zfCP{?00`~!``6OtxexY*FK9*^$>*}n& zI{26S9{9uI6sfCtCU(~CY~=G*?9ipu82&#mB%YmAu^xa|ss7Htv_xMOw8N!%l1Sm# z?8nTw+Ah!!^@=+;_m}Y;a6YB+@58CQAtKMF87HuOF6IEVN71l31oS_L*XNIopR*0O zjCDWwNq!r=dMAr*oXs53fFZh*)oyagQnG{wtv>?pG!Q05yLo# zR|20e+NR#?ykCCT^uI&;TmJxp6O4bsD*hH{kNFFK>E8B=#Qy+;cy&EnSN{NlJp3S= z$2M(atB>uduAwWp4w~KiZUd$mC}EB;!yHjuxH?jyho?$=#wkBktbR?JRaNn|>P2Yh zC$5iH_eb+H@Ei7G)&48$7PmLH*AVH_I1v#UFLTc#F^)&8bo%tKxBd(GMlTKNgGBJ{ zlEoZD%6EZFP3yGCIE_zUGDyiR25J5^zJuY_m9K<;9jHxPRVugl2)kJ#$IAo@kW~N# zoZyf*91aJr_zS_7e+T?OYj>y{nIW|d{zsh}z1-3a2^^7t0pJD)9G*LP*`9G%H=U=X z7R&tmv*)tBwiIQ|wQG0!B1=e{AAZUp0jvGxVN{Ac~J3;85EMl;N?bC?auBt z3_lj?$*Nk~Not11;a6+|0Iaa&o)>8OiNHNZOJkzqrPusSH7o1nj9SADq*7cq*CpdT zu5j!Q2R!mfT;T8yHkskepNbwRwy@E~;eyIMOLVb-f-o@cfx!8WOF29YW0gnpTwPCf zXnUNDHkUe9l=Ky9bH zRY>k77zfCKA17mE0_T=E8GNohb65CbsQgRuHPyF+Uh>}FCsU~0$va4v#Er~^kG~)o z8wYXD&^hXhSY(t|rc;gL)OS3e;K#ydv$cy#&<*~!npOwe8X)bFjI$1dBxETk0ChF% z7C#JpZQ=N?^}i0^&u0?u1+PSRQakXO{fs%b|>VJaY46ghg;Y7dqu_lggwQbUiD`<p`C1#4Q?YcT8@Cr{^*qyGIMjJY*<5 zbDlV;JVBw}{7>;P)pg5lZ&bCj3v(&8vvWPXc?*d80L9LDJa(_RA-vNx`I72b?X9;E z$g?`cvbV6~82+@nuf#nI`vP54RPiT=;;{}RAZjtBWRBan;~<>#{{YsmzpE{riszMI zL*YF?!k#(tCyy^KJ{b6SUedHpN>4uG2DO~bV^9%9vh3XX+Q)8xh@Nv^r)ltiTGRAv zd#zi*`s%wY2-Z6}2s~gG$0{@H&#ne*=${09fAC$htonb6bW4z~+1Yg)teoHzw2|22 zwY5*$C&Rjx)QL8|re%3Jls4Yra6RfC5|rJ!zan8$O7iG@b$9SP$M=ur+W22p^5=h@ zWmi&)bDmF6Obqq!S{i5U-{SZW+2YYPHjNJ8n;BtDdS|aZ^VYtdoA!e6ZL2(2{wdSr zV%cR@VorJFf$c(kaPX!40oTO3WRb2w1=%)_OkkIjeRbwAX`C!MO2Olmd(fdDQ?PR>$d2>XaVO@kVuRKX&#$D*ph6 zarl7nw3@b!tdh}?(RnTbKA78s&~j=G1K;q87o+m#JxAs~KS*WP!(8vGk| zgrCH^0eKGPEqxHk^yRrZ{&k^e;ypKAw)3=0n`_d?X?uB=RgCfSu~Wgp&MP;7q~49c zniOe57H7dXegM`qh{d$JHmES0gFTz3)9Ow+tbIRDmrs?GQ;Om@CmE3lC+nZ3ev8~R z*A~pG_z1b+b^L4QpWBmGFy$55}gh7Bu6`nUz%AO+AkZ zX*`hX5m}THgq$7SKPtr4<=Tj?Y^x$L+}n1Mo(^%0o-1ce@Z|cv+>b1(A__oo2V>tj z?rFN#l>|ug%w(QW3HdRAN%cH%4@%>cx++nWq0O=*mc~fcQ%jC=tCO&T=tsXiXBE)c z$#rXM6q=(+G=v;|;v?ka8TABLzy8BsAC5l@YL~Jyx1DnwS&=?qQA=Y4^&V%Xdp*pH zYU*Z+Cc)Ymr$PBwT^uT@1t#|@4$AEKTGi&%9oUkH;elWnF~On z)4{rkBWEKc~B?_Vu`(i&x!k@42`u1dia*0EiI6k}q5p$jqzFPcUI#cmx_={D77E(6n%zqp2@l9VVb4B&#o)ERWu zaVblM`A8%0Dee#XHGje{aAdeLNQNkvdJUlD{$AguTsJYNB`wREuAnWh&8%=EJU=Gg zpn%MIM>_?oz*`!>O+kpGujz21~ z;0;Dg>upe78+g3f3?6EYjtd?zeSV#4IgHazYUPQ11#{vCo^3h-VQz#8P6SQs_d1+? zDQvty{f}uiu8VOa!8rxVU8?x(J-M!$ZycwGSr?j(qu7qsLr(EU zrn&Itd}9n~G|5EL$Y6glte3qrkstkBOt<{nP2s z;tgL%E;5lprHLMJ3C`K1J8{r(KDn=-ymRrtS@A0Un#)+$+RSl@=L%T#&LaaE9kNFz zy({+C@phTwtv5oKNWX(oX(yg&C5?g1Oh7pxWA87o7{)8->0e?KkTK6E0>4h-?7oY` zLcHnPdhVA;ZrA(Ii_P&>6?s#Hw9{+<0H5Srzt(5e&UF?^Tp~sos8Rxq4w%Wu896mu zIj%!d@rBE35-p3MjZOwef0abuDAXDv1n4vTLNS{9XxT4yXn9hm-m;O=c&c=dLA&#u z48}nBK9%RU7o`9hBaF3Kyp`_Qz1)v8^~;=!%D$L}A;w7*o|?0^g*3F>WzEo+_=8nP za_5>!FptIt;ha-JJBVRW-Oo}K`4)nL7q3HBEj1}EI8(U~@S3c{Bbs3tJk>>Cs7)rU z)`!yn0Ps%__$gn+FZd@v#kBDk!7Jvz&@bkX{t`b5-Acnw@eB$WZIN(%xm8{EOrWwc z=*n3e_B+NO4}K1R!Dhc^+s}y~vP7G%?J*9wq1{HY>RJ`cDPbMNV4fHTDI$`N6|i!w ztNiu&UqZjv^%EC|V0)W|UFI|+BzHI`p0)R9{1dmppBX=5ABkEY#V>=J`skX}uqxkZ zli0~|VXWCc8SO8Ey6#p1dJV|HGB9NXa@OK}Hw)BNYgJL^(Z$`VFEp?B*yqIM^Q}rX zB^g`n$tR;-FKt(Jcz^9x{{RHzzW8_Jo7m92+ z5Za!HIsX7k)2G{(RV7!=k2%{Y190l9+m(Jt_zR}$KMQZKJ|1}THiGv}cb80O;pCf+NpYTZS6U1>(eei9Q!rI2uD%qAVrd+pm1D1rJ_Hv{9oaA^1!Ow_( zA^11rD}RT-9W5?&eOk@dJu+#6srhlSH>txZ{s#nu(>*Ko+gZ_})-7HOES4O)((e!0MhF=ivz9VRlWvqye^hvUKn;4yOjo^Pj zL-RIoMf(=>E!&s;m_Q%+{X*WI5^EaPowIeRQ&t>=>56>0D>TY$}fHxXa1tU`gXmd zwEqC$j(Q4sXZ{Jt@b1Rl%#p&{rq&~z9aiy%e>_oNnqpw-)|_R!ZGI>7R(S_YGQ~n$ zs*_*&Gd~-C3-~7c!+P}E&berHEn?@)JEGY%n~B4fZa@Kta7I_!yT6NCE$#mRi7l=? zL9BmgTvP$R&&0XV3zg7R>mj?`k<|aQzu=dk-!5y@Yyx+wE0wdOjQ>MD92;Ve0ito zo*3|@!&_NQX1Zi)9oC39+~KJa!zx1 z;kWGLt@yLX7dq#}jc5B|bjxCv@UlFK3l-WB1N>h;P5~z)BzIAgQrJ!tcC=0i_{&uI z+2SoO4Rc?*v%0#Nx%(}?4QG28~}8}AZ9Z=0MN()dejX&#Xuhwi>d(>(pf<0{e#M-3{F7`ta4r;(A9 zjtlmL{hstshu#Ue*S;djCEln|jXzE^48-3vB9WXU6Z0|Z6l1qNI6NI}&k+nJ8a&k| z(n)o1V$>cPIv|}Wk_VgaL`4{mn!(8!Bq}R9C*GShOvzKB6 zmCsCe1Ar?_;g^FvMR#*ycJt1L?6O*fEr6;(E#I#o`v$Mvv%d^-{twCJkH_Mq=8{S& zB&9dBQ+nF{f0Z|5=jEABy=y4x`X6U}QSq*$`%QT2J!iqzkuII0vkli5U-9n-(%ERj zkKSNzIBf1aKp4tTDA_D%S~;jJc5?B9r*r-xLFHJC~E zh?gW5J0y{a>74A(ew}mpd@!}~QvK8%yV*DS9-lJiQIoOh_nK~v@Rr+7(zJ~t{h^p_ zwphTPMoe+YByoZ=c|Cc}aTnUm{{U?l4PkO+bIff6MvxQ2oMW7FGCK3^ias^?`=@Gt zIg%|e#aeZ~of@KTi(`4X8ON9#mE;cNid|>MdM2#_xxDc%opG^#SiaVb#QLzv#&MqY zq;jlWTm8iU0Pq=qk##F+Xvt}?o-oq1pNKa$(rOb}Y!O5SGl2z48? zHmIzPZ24l~?9XqTJe(h1)zDg9$#-`QR~E|lrG#OVjFK|AV%Q(9Ym3#qZw{-ZSSvlH z`&%_#Y#twhi zkIS0*&*PtrlgIx68TB@@e=|t8Sm0ZTu*i081P*!m+4^HSuY@!$Q&magwbL(dM6$@J zfKT%~5*OFjzMim-(@VdS*i9&S<5-y$ix`Mp5_^(*@zWI^B=A)p42~W!uIB1MNjw!Ya4da^8Vphw%ThNaN5{nEe#%~;I-X8IeuWzI35>IZo1r}J`sNY_*Dbf@&tEe> z*sso*ym_zQD@QfO=|G#-Mv#D~AH)70)#|^q2gOZRPa0gqsm|BYOJ=;t=Ol&$AcK%W zVeiF!*A{q7ERQL#kB%pw*`)2uYwDBh(Q0Xj%p+E!grlMDe-OSLTX;LdI-^ghNb2!} z24*T1j~iHbA5L-yt$BWj3fS2~k2JYJBpZ7kxFnzF?OLA@d`TyaudkcWwia3`NOr^s zGO^AwbI2I#dXPA*T@v)(h~%0tSw8s>HBdkO#2rD^E#ls3o^q z6&i4O0|8f`lsg0JKb;QdFpHCB1i+}djbwQ)<-)Gf!V)%-_y8-m)VvXEVXRnNX}1K$ z1Pad~QVC*D1Oi5Llk7Ird4Ddy!t_;UCy9 zQ@FK`qrkPB8@P2s`dY+bOvKS2 z^^Um6A&4WnI3#n9Ynu2;@lE~&_?q)T@gTaBNY}2~^1&_>%KJX!`^4w(W0E-|9CaN1 ziQ;eAYS!;bjxPxKk5jU`=Q7+u6zjVkcI_A$`q#>Tw72X7@vaRD_-MCw-YT?K5+~Ub zION=?a^V?4&mD;Ludm_m7XI04olIpKchb|8;{2@n9Dnj+Yff}M_@>XAzi$r$Xr2xD zi>J-tHEUZvLI-!V0IXK-9OTBm6+sHF!+3f$amx2vO+IML(XTH0pBIXpDq`g|8!pBaNFo71&-JFwapeL(g!T5PKOlqD z)g3}ZxBzf_io<1OWeBOt>~z#DTC79FhmjX&jJv=}El$)@m)C&S_{UZNTkr{W06twmdKJ?_KetIq;s7 zsA_8;EY{F8ik`%d0q3P-CIeULzx)%w;#59A{hoBlH4_u+)-NqnK!(soNrr@i{Cd3XH(05^P{W8ue$;gas& z_e#`lSURNfG)_LMz!DE5-!2oR}w!1!43!3_X}v zb>e>n={_&h+SkOIeVyb7BW$sQjP=3l57NF^Zv)@|0Kq>#FG~PRLA1WDXr687!tWE# zvEBeO+9agmOaB0|&I69v2aq>@dBtjv7iH;1a^k7G#dMPE6#Ko>eNsugv)97asg}}7 z&hWk5ZMRNktJk{IOK;QdABH~^b&rGIGPc(I6L4U!0Lm3d>0fS%5Ak^^I?I6GSyago$8uadOwQr}wB;Jec0 zN$su>NgRm4tAo&jE2#KS@mp2+H{)wfZ^Dx}c$h84zU)VP4ncTi;QXuyToR`YIRMw@ zd@03vz7xf|l)dV5_i9s@!#M2IUz6P$=Gkk<#u$t=xobmM$$jSjf#OLu>$|Nl#Fqa6 z+1@77hTF?Cz>swFV$W1QpTbTLVq351(d$-E6~HSla*jHouV47@@OMc4uRa;C#BbTo z>PtTo=-FwbLKf!Tz{^D{jPuSp%CKNYRjcMd3jWe|b84qW__(oX8tf0``I7vW*GxF- zf7QNo^0yv`u=F^`f#C{K&oTt(gsHDC@}~O5_vL+iYqqD_aK?QeAj3L!<7&~;ar5rH zpWyWAbHqPxAK6L1H~1fZhKXn6e-4v(qg|=m<=3AizCPpNW3XTks6R1&&%YX*;$Dj+ zdZ(GEc#lUuRsFdJCs)ZE)O7%mazBLRdS~?a#eN%45Lqk1v+XD|8+wmIeLXAk7xwVc zEF&4r5b=@oJ{7jI@&dSDO4*o}bl6{1E$Axz|77mtPC+wRxK2;z6ngk-D&5 zTJc7GcmtX%oc{oWc|37z@gx2S@9=k9(bhz_zfE0&IKv|iX8l=D(UpdK;)?wrM{wa+6+{c0NlutsF)_5mpZBQf@=F+Wh}KDNuWO99}Q~0E9!pmlk>*q}p5(&NtmlGWqhhM(JhR$7&DmgUA45o-=hD zT{lI(g4+66ytB3#(jwA5wh*z~(Nu`kvo~gCJuoXL;%AO*qxfH`>oC}?CM`)=7;`6< zr{+XZ0mJOsjE|SEUca9?zFT!F$}a8bZTw8u_5T13d^fi6{{V)rH0?7}@dE|ZZQ_hV zVM5?D6Z}$@VorOL=quU$AK+y0kHX6feHz*r?k%7Qt+*Mc0DrA^VZncyw;s98e7o?I z<8O+;XfKFR-|2dOnFfuf+`|dFkxY|Y##`qByEA}SBOM6un)>g?_t%~xzO))sTSuWJ zEY~HumUFioBMbLPz#owM9E#k{l}c)Fnm;f22bbu+Id6elZ-~50@L%G8$EXg!;(Y>3DK$dU#3PM_s}XbMhI7<~+A=UOI&~-B zeg=FGxs&2u*Nc38Zx*AZ_+YTmY#~A-j$?*)DnaFV$>)+kx@+n?4;r_KG%iy3tp z@3L*J(KaMN4mY?MQNj1)fnQ_6+3VqqQ_LvQjH+7E=KD9@uQs&5Yxg*Dkad4`DQWqi zl7AgPWnU2dFz^`GJ}eLHO)X_eTH<78+*t6S4p^R;{{VQL08L9Ju9KjAIPm`fj4k#1 z3r`B@ZnpA6Yrb2n%bmfV7}da4!lI1s!6CUhHT94D6bDl9r|n1LFAw-T#&@^yE{AmH zJ1sLU_UVy9b_1S=-9x83ZQ{1$M>4eU9kOLrA$(-=#+oIVSeF?0fmG5cqVz3j7VEXb%)Nuv);P<|}eHNh!f3wmNb^?|>`Ro5gm14e*WS=DT$q5!y!A zGD`e}jd?4c_yh4KyZB>{vHT~5cx)sgX+CK-wQtt@CH-ns!qckxsynmt<5K?sf?4?f z&gw>kO;zlEejE_B@UU(>3kK#@zGy zA#X-wJOu@_IX3?Qf^Ycq!ZuF29SO9Q^FARAgt2`(nKX<34j8 z>BH`3ZvjtbbMrUhuk7Q0@N>scaq$M)6uU65+2fP~0A|5rr~TXxJDT=u&3eiLZ*^;A zk5IElfsW!CbI&6r9N>SAW&CLIRNgW8o#HPLK_PuU-sD=sfbk>|8@ z;|*>dSHe=uG?3f0Hs5G7F*(Ohc=aQXZ^pkV;%+3w@kU`hek$C}B$C-AtdjiwTRJI5 z7)Z2nA0G8BZ{lx(=F)r(Z7tf#G-m9^r{z^8f}DGWKb?4npYT(~x`p|9bc@AHRA+J{ zI2>_~G3j5V->}bs{{XW72EM7OG&9Ms+_bUC*kbXi^3-FfDi0xe$j%LWl>Y$R8ZKsx*;ECm12%RI5gN}wb(Av zfC1_34>gyn{65v^)hA6l^3zf_$(f8SPnI#%WMjTEJDT0neiiGUF1@i&?5HM=>STbc z1QJD-11xczjQZyp#%tic=kBy?PIX?2Cy0DV@Lr>?>o-jfhjiBS&mo6mk%T0b7rEIgZ6N6xjYOHVPDf2e;O7Zlqp9Eq*6=X?5)`5sg|iq?nmR*=fi&yX%>LlX*Utf z6b>Uio}=^?&uSkGHSaIXpGLcBCO_m*bZh>$VoaA@U9VmV`zxo6J0Lj1L8AC6#w=wwjsCXa5 zaru`}={GDK900wIN$~f;z98^_h!$(hDJ+bTzGjj!wgoH3N$I%YXRkH;3on4YIrhbA zw2eMhjxyUty7EW&xaX(xuRi$K;7u!C_)p?=hfTJD{{XXP@_eWla_j}M_4z;_TJkgB z7k{>L{6+=gEUH3Lzc$xaPi~J^Me!e8wA1v3cA96{kij3!+mGD`JOS_9uX_G`lv1_#I_bs~?4_)`BdFH(r11U3 zHdbcZ;^JZew-}VG6Wjnd9)kz+uRi#T@#g!&Gs&lD_ID=eu`=A;M$y8IcsNV|-^=S? zaC`y%mbAZv`cztt_=@wyN0yoS7U8g*-#6 zSQU02!xGE>b_kfO8N8RNBk06?r3B`4!lOCw;$c!N3gH_2xrp2py~0C z1!vGyakzC)qUM5D^ptk|4?0va6m^5S>b?N~0D`ReKg5wjo-(q&(dCiGWQ_#Tuc#zo zj()ZD2ZO(89|n9yvj@Q5Akwc)xdlAXvL9`&&VLI0+VLms9q}{a_KwEyLYGs9)b43) z@gQOAUSX_h`k#X?o%IyI(=L?YWm+af_||xj3%GYZi>s63xnGo&&3wLL!kL!{(}fIGWjZo# z#?9`xe6MR?eRs9b7dXVxt2pxfO!EH#fFHAdzxzsfqfpYmAN`qbH0vh3k?tR25E)b` zKi(yVK8Mn?ekJ@8@qfVGYs&b6q1;%!XA2~-31F0a5(==dX8!xR>rMt0IuBdt?^p{hIv}yR^|hBlviw+wq-UgLXhCyJ;IUWA> za#F@(kgJYCt$zXQ-|&lgrq=Rb^;y|3`;EarhhM_KHOiba{KlHbM#?g@lj&z?b>#m5 zBhbT2Dx_SsN4DyI64Nz%a~`8(Z6f1?um&GOIUj{}zp|f*C-@)ZsVy|?r~b#)WD-PV zKk?^qI2*lD*9uQuh0hr^ffd3@3cO4i90pPjau0e<`(G$XAIiU7;+_u6__GB(EqL;_ zw3x!NutMHM)Hn`YGX$5JTdP9y_~E3k*n^$&I^;PZ8)AUMkUU zwBHe1MR#L+5r%kVUCAPmf(Wmde`gQck{=6e)|x+$ZVXZ15d?QqACgx76=T`QWBfo7 z_pzU=!>pCi#`VCgn zIrQ0Lo(V?ek~R#kJwY97&i?>xkAb#79exPvHX4q|uXOSD+Y6j?Zz_Y5an(we1bq)s zE9DQ_pZ0|DH^b?!yg8`dwZ5&SF-dJ_#F5+}?~MK7#!BFkwB+R1i=A+T&hVewxLqnI z%RbV2H7_R9*SpudKC6dv*Nk6Q=Cf_6H?wP32KqZ|9{Qv7%l32qq;*f(f8s1&Ak!ka z)UOw3C*bCl@w4_?oi(oq_^#9K z(a#htgrOx^v}^+-qbsC{z!ha+Kq}SnZngVbYTBNGHLbp#WovUf7|iPILIN;Kq3C@H zC-JXL{{Vtn{{X>7ZT|pbABdO!6!_@xckn~v4CvS}00_m|Qj4iU2*@$HD3=PW zxs_5ulNQJJ{5hT@D5qBgkNzCmvc2s4uRX2bZl`u-!MUDG8D~@@YLwr-6z|OswR?QM zJ}#R4?W%lI_=E5g;!9r!_={AtvW<=)VzWgb`>7yczkn6<7wtWzYTp$#8_yN$SGSsm zvm*&FS=_VE0__Y3KvWC>FgA=1g1=)w;HZD_O^N;*UtjBf2Uu^kJHPacLlN8zY&Q%z z$ScnTcCW{;jDHceFNPi@mf7@VMOGnRS&6|Nuok|XAHr3#x}VxOdMlD&X>#hk+ScBu zqf3giT<;F(RjFy)Zdc5o-MaNZr(gIr@;@j32w(6ya;=Z;?pLAz0E&ZBqO5 zAMivUf|pTS#cC&gef+4h5l{Ri8kTSmPI^)br2TtM-zx_)(~88c&EKiq_KR z;Lg(&Ew)9@Ne#i^k;wik`t$Z}_=^7k8L#2f{4SP_rD`(aX4#ij>RGY;Ba%QJc&~## zHFzsh8XVemI&(GMt;(=?$zWq`*xF7r$i{F-Cnu$4cmwv7@mIkeR(%`7x1VFV2$9@6 z&xMUnGBOW5fuDYOucF}|7RGU2G2t+aWZawCFF!W)OZ=I~QyukWsm*A%KWNuL()2Ah z-p5OqYzYa1A1!e69(v-iBT{)FZ;+4)J9B^l z@5V^Qeqi`l_V4li?Zus+gRb3So?x=fH%#FO`IIr_mTjsqI*tW>Iiz@j{2}oBN4xRv zpf$e`Ubq($UNZ#KqXfBT1aKGT+Bn=t91PdfaeoEkI5!VYc$$%No3vuDeK&rKPrVaE z5V1|$rtIdlNo;j5it_8)?!j|y9NK=Etou?pLjdxhloKS3**=46jNp^$pR&Kg$aQ~+ zx{rx2qjk2^P9bJYq}MLIu_PRo9)}ra$4c>=Uy6Pe@xO}g<9MQNF2V+6o&;%PDi_U_ zrI~(E2|x(wSxyTKSC9Co_VMv2hvm7C!VmqOYdgAIqMR%$SnVVz!60=t=Wu5NK6n8^8Kn+&eb3cD*@j)#xgz5e$O!QcRqzL_IDY#()QEld2cYK zD;|mBKN4NTrZg7`6Sl!;8oR2>j?4bB@z@Z5t$M%gVepFU$DbZ7wOQ>sxH5^P8;SD|qZ7|P{wG^<&iWGauiDOlB6vU>Xp^00mm@hhm6T2YL9^C#)G*^k$0%ULt^QFJI?-dkzV z#_r+cofLq;j)y0wxUOU4ZT!9j_%W^O+GfYNh6aWl1Gq^c2!sL7MoIiX8u$}I{{VuS zc*0xPo#(uo1b!o2F_`qu-1Pbm)#`r_e{J6p{CDu}%w92q-aR_rb@JhmZIWpKJOFq& z4e9(t+NX$oJ{+o3%G6>OhP4HfUe?O@OAbW>tCB z81%ms>*$i&X~Dy&C0pi3MHwCP!?$Bv;PCY^n2LCMG3Jz-NiOZ#BUsdQ*OB^nb$TJx z?NazCiO$t_9UJ?j>VKEL8jY-$H}XervITT9nFmY`0`ha5*U5e%{{VuXcw%b^rPH7- z1=Q*Cyr*_cWt4DzKM%^fD8JyQ-WasgWNX+ARPLnw9HP# z0vsFwPan&Q)Up2nf}r?fYdMw+RdtTtc9SmdS0v!^O>h=`{{ZF|Ux6-%YbC=`+ z^!2M6Py7{M!?sdMEv<|tr5Rw%MltQ0wZIwtzvdEOhxv*)%3sWVcdk0>I)pIUxm1{A z%Tb17>fYa9O3&7`Ws^+5vz1lW>ISzsGu3j^5Qm z{{a39&!UUPiY+NJK5XtMJYZn|0QIO|9%t|VVPE0?Wc_A>eB8&+9y^8YylH!#oc)72B6<#KqVg?nGK3-l%PJ0jMUq*Zz_$HsVkBjw) z^sC4;)Vj5Mr78>gQ8VR0Qcui7{qOco9x49-f=Kv>NfI}L^?Mt^xUdp73Fp+}y&ntk zc@75^TN9sDim4Xk2u)ol_N4T+`YzhN>~YtnQhL+boQK0N_$hynyeTi2;+3-1{H?8t zJ&qOO)N~Kial1$DOyS<`q$& zkQ4b2T-H~_ulOxDihd#dFx0ed7sHmi2BE1!V*b*GV)9#zbwoU5;B)*vK+XvK_cie6 zIpLPEPONz^Whlsvk_jtDJO`jDYTMKO}Az1>U@L5OBG%-p4ZWK zIh%qaU>A-vUAMx2+F!Zch?Si3Xy8{k*`6`xAh zj8R$@@=fl4i^b>L6JN-La)9x1xBW00DJ(*8Wp%wV* zx<-|++4-Iu)gXfBlJ-~3A#wiXrxCdH0Vo3km4xRp;mP2)KijeIVa4Wx~JFFDost@Y|QBnLYtaE zb_3La2Rv63r0Z8c9o8+c^eJB6>dsY`CmmIR$oh|C!LKik@wrxcilZe3Rw*?t8qvKH zdNkI$uKuTVa|}Ko7fz(%&mE+@r`xmYpMRP9f8&pjBVW)avC`~hw`;Z8B$7C6De3?N zoQ^YJE`HKq3}g|E>Aph!pG&@Z3XQ>;RYAuf z5KkHQtX)s`qPe|_NbK}`MMecko?|FrM<9R}yteZ3wHwK9CRo+yb0Y*miU~RSRB#8d z;-ksj2q@4S0_K0K%RjvekSqd3UDj8hq(>YjerHg?DSXX*!()eVye(z zW>Q~sX#2b^UvEYgf0-xutDgkv-YL`cuMN*8t>j7lpAas9s8z?@W;q*kl39oxDIntn z`0N)F>R%CL*5tL+rh*2xx|{4yf=OeVMnwu+2MlmeIl##kx375b!u~4KZgeY2C6fD4 zEe*mnLQ88f#c*CT!2&c=17`qao^e^4w~DlnhI(Cr(TCb~jcZnd&fP+@oAQ#C0|z@( zlEu3O9C9o3*-K5&b~bzLbN>Lfh>yZrCZT+9OTOMWJP!Ja4hsp5OROT_L4rSQy9Bl8|e-Nty~ zN8z7J<9uKL00h9)bbD!UH7&x*)dtBGfh^d|VRM`S4o|&*Pxx<|aQ^@aWok9C5moAY z)AH>f`*nUTo(?{pOkDI@Esqxcj{Y0Z6tnATZ@qjpK(J5YYv%w)S$pl?2p*+Mv$w-tA4t%qlT+6`Q5lENke7FI0JxWSPbYG&eMtk1*3ZKqh4z05b&Jb=KIQ@8 z-wXM7li2xX=DNG`)zU{9z{8d}IV7TgbXQH`KL*)+UDo5&J}g@$ z(nns0Bh%?$igD)_J}k~^VxZr$UhOs7E3Lo0?lq zg~#mk4UUU>Yh`t-A3F3-?|~oiq7Vt{26}Kk>&$hp*{fB$*A~{w{{Tsy+46_XeDVex zmHcz*Us-q$QXV7Mb*m2!!F4v173A+0p)dkAjf)+qLuBK2GQEdv=DhR7*W%Atxv;R2 z<6@u$Fe;MZ5*8u=AZ|G=lfWEvTI8M~=KLpvSUkQ_P;$GxQ*G&cx35ILMl~|}ScaQg zBz*hg&)Jty(WQdcD~%Fsf%8eWcP2b%l6C=tcuIbPi@pU(x9iMUam6Ybincx(1`@s77JxP2!f z)s!%i0V+R>C4k2x2fs@9%NyJ18us$xW-#1*;oRrU$-rTe*XADGJu1hBym51;UdaZj zZ*w8?%ErK#RSU@k4xPK7rxn{D9QcYGQ>53NW%^AS!z!aDoTTmL{{RemPOqOX`7NCUK_?ruj=Gqim=)VF%` zU24}C3lW||p%IvpuAq$WZv8rY)Owwb{q6HhtlCEeEQ%6E<-}PzTyu_uaoh2)o#NjU zGd?oHLkEn6BN)q@+)`I|X^lfzA(6kZWV$uYu>({v~NDV{rl#DazqM!65PK*stpx?=*&8 zmtt{hOZRY;zUa1(Dk;iJC%fKwrhPe*Eeh)1Xa4|}bF!84`Nz$UNcQM!f5kp3ZC}9_ z#jT)yLi%@Tj7nF_i2)2rJhtW;=el*SUs>>M7E#XjpJ_vMa*S68IdOmH|-aHE#HNJ8^N0DH6k@2vtfuB9CrSAuDbKY7D7Yj#Uyey4_=qK4dLJqP2FkHFO4 zCX#E5NncKZ;<&YyS<%KfV?QW9*%|z6p3-!UMns9HvX^W?tV1~`ugr7Cae8&ookdlxE)LgVHyHgmt!aEMbS{k2*-V~k zZOMW{V;mOm-e3G|PaCk=DC3UD z9=NCySgiGidp7f0Hrh)j0QAVNlT7f%{L)1hqh~Qugf1e>GJ*)sdyI9f`j^7>mgQSW zigadgx=@-vu}yuY_m7eGIcxjRvR=+ekWHQH=Q!k?ew@{4FT9yp$GA4q7@kQv>zeOl z_)Dm2cEH@)$XOHQa)*J}rDMzRqfpbPDF&Z%z>;z~89m1}62#K}b@!n?{ZbiaNlr!{HY#vI7%R(XK7jFx`a|Kr?Tzsi>INwEO&?iS1RxBtG>gYM zVh4ViHT++k<_Zw@c#hq&UA&2KN%qoSo>@PBq;LJ%#$WnNXGCPD zpq?cCkv<>z)(ePrjSAf+QM=BzMva&p^PZf4O7O3bKk!d)hF%`>XS?xD#)o*oG%yd| z%I7={tA^R0r|#ED@tgLm@fVA=IV^k=aSnqM<`9q#vzH?{GO_85a=TA_*Tz4zm&O~v zhxa#eOQ>D9h;ALRxMA&J8S(S3URnHLx5kgTa-F;iZxwf8%oc4Im?T72~* zbBq0^Z1fL?w%489qzjb6;y)7mCKq+G8rZlkVT(mdSY|;%nA;iSw~;q%NN^KgzlP z02H4x#G`YT6{|JFy60)fxW!@kmTl5osP4p(^c9ODp07ikzJ!H55PDWb?eh@BB=@eS z?%VAV=Q#B>fvH&-+asoPnoc?%t`@3oBRLlgK_5dyk-Gz}2`1+t&~f!XwVZc5<*E{j zD6NcwnBxcQPoak7;B!+gijL*a4Btgzt6RO?Vn~s}WhVfR^<%|NWiN>Do5M))>Fqlk zbao8rnc-ND4mqrq%xnp(P@F>H0Lka;SvK@t4HQ(J`j9k=7=x4Aqme?k2?sRxLO?7s z2V8ZinaiihPXywcE;_wNrenx_W3i|9s8&p_9DX#bDZmve*r`XEs}cmr%VQYMJJ-Gc z0Kqr^0B&y*{{X=~ziMv}d`0+v8saN9HhRXG&Qd*RO_Zrj+jqhtGU{gD1B_($V+?BU^G7<>o6O-sUFCANJ_ zPPkMkStXU-mC*8zu3cGAD$2m}D6f}4;M!R{-}oYD!B+MD-2VX6_M=67wk5e%o0Ge{ z{Li7nMM8x*rJ_snKPS8?YZO;^ckpUgt2V71(Z>e$-iodMy;P2Iv?x6=bDZ&CNdC&d z57*+K$DKb^)9xNyEgI2$r!j_8y-LOzi6jQ*LIyfU58uUnzu*f=bnOCrZ8J?bdd{%v zr`xz;Ub@!(nMDK4yAQn@ZbU_9nNsu(X0Z+ldp*D;Sf1Dlw8t>`qBJ9jV_Ebp1P1_-2+` zZNgkEgo!3r1lKGk+w+8kw(Tpv>X%jlsPzOVma&YUYwV-rqOBg$us5u02s-j_;X+JWu2?EfrNLA zuGuXr$niJ;b_|LE1CTnL8n-s1{hewpbab+s?@-ciOT1BxBP=XH$>ii6zP#6{_`~*P z@V)nmE#}m82rdoGP{3HtD9DYAra)nllHZ+L)BXu~KS7#(Q&Z95mhMD!oy+@i${d~HSj_3w}GLx)DwN%Czj9+su_N&T}Rxn1>lb2)Dl5_59-Z1!g2ZMBEYq$eh%&KK*6!qO(-y5a?B#JQIW*;Ezs~3k4{< zvTE0hjgmfL@e~F17$neb?cug4Rqf=Eh~F9cxcNcjpRdxd_^#F+D#Fq$HIK}ZkK7qZ zvDb4E$MgEvs_B2RGg@25x<`z)2vuJsNo5q61muk5cRc+oeoxri@$4mNd`}$nNsX-~ zn|!1W;7i{F^y^sE!%q4lXjFnvx$_Ohys_LyZOD$)rr4Ao3CKS;>OcKeythYM(w$+I z;*O&)J3hKxxBk%a@G8+TxE22N|LkM=Y1Drr!N zr_tvo5`o~jkt8q49b>`t>)x|iYM0e$a$PyOGs(Oi;0wR_NUSdJ8tZhArgvFT% zBmVjC@7})8*Z%-#j|^Dp(A(T;NcRR6UCO_B;|00nB#hSy@CWu>@n3=UZ5~gGl36s@CQk&iC`@{U2OhQUn(EDSsuz&H^kO7eo;A`s` zk_|4}W_bj%sor_y05Qn)Yd<#TyNK z!A4IMw2|1~K#bxUF*7+CP!B40l0gIyl%AYdC7_=W+jzF=SM2fWYD>oQ$V4!1IS=^cJ1lXzN7yDf^vKcwein`^?gUjR;KF4+TkI9 zx%opfhin{jPsz_tE5N)1;;5w6mqFK3(e!)dF{HDm=`H0|V1;l=$1D%Aue*O^{{Rim z@aN#9@#u+aQSO>crdi8|A~@4<1mS+}1}nEMuTu+MRih^vE9$q^TlFTDB`I@sDR{T` zQ}8X+@!Q9wg^C6;NH|^2K-_w8GC$60uAloOcrmSaCYlPl*tkD;zomDVw(`zA+1Zx^ zovU33hpbCl2b3yAxed+%AN^|jH=pKD{$eNp0D&^&PBQx^3#R_X{{Ro=wnHYCvO4fd zJ-ha&57`6Z^{vT^`#vT(I85OCcCSKPu>+s8oW~d?Pf$;#Q~uGLQNHrtEv&>9Cy(>q zr~7v>fAbMP{0W;VQ(Y0jU4F^l3%8j>IzsIj`GFYYx#Fsy*{8xOv6Du(05?)H8}aSa z^{+$Jq+*H}A=&UV!91Vvt8&No%P1DoL6D`HI2?`-@*edP&T;SlU(f#l0%COF`W|~1 z?DgR9Bg_8CTsb2EWFNwvAME|$m5cWpLva;T!tgrxKj+r7mS>E6)|dVS#GxL?#s2`dAHrLI2zdL$lj#=gr&-NwByuPmNL9Mv zj&bI6_OCnehlryWF9wZ;`z(hWmngt1As84qIqTaV)%54>^>wADh2ia2#Pcjk9n6-& z*o-T%1OuP%2+!qTFI;%q$4-nkmYz{ALV2n;f=)>Ts_^^+@AR*n#?Di%Db3x!thD15 zW2*6HjSSK>l3YET909fwwm{sG*Qo3HRV@!nfX5||+DsD=3d}RP$UGJR;E$(Id{u3D zrN)?%LO$EMeCT_hlnf9$a&yOA{uSow;=Nl+g5qr{?%KWcRO!el2TrYkoeyH*y(1&i+c|lfw1uUu56G zeXICPTv|!x%O$fi6;qXB4n_yASaI8m_?O1^&u8OZQahc-MY@nNZlsncn)|K_jBi!- z(D^FyF>R3KU>J>1IvV7Ucv844Xn@URi9PIKO?Je?- zO;wrFWh%fGr)pCb1inI_z3o}asRt)u1P+|?YMWQF=)#+7@hj>!X4&^c^C>=+RHx06 z(DPce>MJyR7BT$ll+bO-U%Obn9ns%PPEqBS<$5XPZeNy~K^rJfEG`*QLpLF2kKK*JOdVZ8pPAIVNc0%j(oQx6L znnr3#)SsI?(@Tw<)^FW928@HpdR^t%@9KH$!1Saeo_|V0K_vC(=}EDvcR#H!_%>;` zf58!c36cK*QQ!SP>NHY+!Ls~+!4Uol^+1I`t_u2{{Tax5$CAiL+ES&0Nc{zqIFSpZ`9s7X4KBPZ@nZVIE9Sb>7fBb>tFGe~8wh~z;Fb%?#(C|@_9=V_-w%Ek=`-0W znQww1jaf~?JN@9{cm+my&tA2)JY{KXzsY}*)fBGotz+Nre{V>&TRmEMbbE95IAXMc z1mUHYSAQ&R1$e;A6VPDSHQ}H5C?r-iupx@4~a7UVwBSsxa$l&%020iP5@CU=~ zCg)Q74~d}PJ;d zH=xb}l~&`Ek)F5}*BbRD9c^&Y%KZux$UzaR4{!aYx? zyjA;CcuzybSNC^z%t%6}+1&LY=V(5Lu;Trvya%dzlMQYqjw7`1fx*e@GFH6D$G3Ve zp`)~ySBUeZrHkyrljS)1i1+%KU%L zoRtzj%G3Ti_$@5fX!Y$U66NzG;cz(YdJ59A_`%_QVpWdA#9A?zkczjd$KYG7es1fY zCDj*N4HHM1SIZ3~ZiuR6BN)i%Y1~g8shTFFz8|-iXLOSKcNs=P`Rkpd8P7DOjQ;QA z{{R5N$s_d!9a7I#pL|-CjObUSb0dcRYkR@hkwL5%zK}E!Fxu*JGJS{R`Pb%-hoN|f z#WP#OWRhD$B%qllK!}TyImbEUxcb*mJ^kH=ofVdcb$b!BAzj49S(~{y$2sZvQT6D< zc>X`|2vhq={TtTxwbtb`T4dXXA$zlXx4*Y;l(!SD<(zU&m`rE`XQ=>SeK-U1ug`m5 z9{7X8ntV{$>w2tHhQh}k%!#|dAT|f(U5=IU$Hu-FHiuo-bszM&w*cjx3HX9%16wo z5mbHQ*N}bd()I6;-Z6tnnoTEJiYK&BHO0(PHst`4Gk`hwJbTxNcx&SYpT(aRYx0=aRVj=ia4Ds$6ZiP*++QksK$jD~+E3+d%(URP1Ds-B?d zkHMGoKT6i{{{V$GFBHI*R&iX3FC+vbO7NNf*JF_#!VD^4 zXBootf!8%=*Y@+(d_!d(iKE@Nj*$~3uIqI^VgPv{fsk@}2R_wwDLQg)Nu-x!vRI00 zDZ%K^x%C?;?=%#W%?g4G?AywN#&g_ttQkC8VWZkCS8}(>A&O2817LN>VUf*zt?V_pQ@aEao_HdU6n@aYBJifCV;_%hQuFN_(rbvJ zSYU^#Oq}B+{JizSI2_}qo+Ay-Y03PME@`X4`q*kV=D}s1zjVN`kr)-mc*Z;NS(5ml zNK51PYm1h^8((4CI({dud;{@c_R#SsgOc*v+r+nPs7y!Mp%zgEfNwjPoxFws0mn{x zuMGI5`+0m$(rn?5!^N}3b#`}rwypJ`P%J`N-tiCeUeq-36{!3oJ`nyL<&FTGjIR60FE&bE> zqHm7YQQIomT28WYy_*GFob=6Y_*=(XXNl*9ZKRA&Q)?k58#wFpAE!$EGL!bG_=R@A zH;lEm1n1?sEBvan{?R@?GAoZ6c$HmF;K``Uq#vkibvSbmC1}Z~>Hh!(Bg9QVdN)Vx zFYV`|{{UM5AINQlNuOIli@y}fN!8*s{ zDS)tn_uJbd4Y804?%nsYLFb?3E9O@WVlglBc3T-m9^*nVh(YDPE>XJfnT8i00q2RpzJjM;BXVn;*E`t`0qOrWP^8|KI zJb(h3BmlPy*C*fd#e6gSW_T742K;Ngn?Qx4(luz~yRsy3%d`W}en#)33j6QG$$Oz* zY7=VqlbcYYJ@{2oC^-dz=QtkR0zRGz`%8Q~gX5RO8=>JL=V~4pnZ=ZF{OvR2GQ_|R z4%`3-c+>%g1om*&Jz#NbpW&8|=eOcvoZ$YmhUJR)maF>oJ|olyV_v)*)jLs?+IS+g zF5)sk%GnL>IuTj0oXB@^&r1Dh_ypd>@-Oa)_NX`Ri}$?%!K)Je!%#K?ob)sfMh3g5 zS=(AkcQQso0#5#!2d*oIn(8~Nx0=y5MrA#R7yIA5)hvuMwv# zj{sx4Z4Y?mizUhN2q7GP@{g!!)Kc`zwa}I2W)M9afA1*AHzjH)h|S-yIckLA`q}-T zY;Bd^B-9IG{k`y%rluiw&|%#y{?}yrz85I2c2>((yleXA3Sv=dX|FBCXFI{uLf+c8 z=&xK#mUn@~Fw5HdgC|W9#G4nM=hGGV0CVYU`r1$XxlnqfLqAEPH%jPt3KwPUgo#9mkoy&scYumNDlg$ z{*v3(m48l|MK?ch7^?FcB==JEkm9nD0*+D_@Qw)UxIw*yZVuEleY0;Z;++hdU*iFZa@#`rZrrm~j)XxK&f5@ZzZXP`zExWmYGWw*Zn ztkbc#_7hm@bUCB`Kqnq9{W$`Y_hxzg|d;dvSvRsRUbBkoLgXn6Y7NrdzMKKGYS#=)PY7MBgYts+oWCDNpbJ%(|;u_@y;lR&bYE7rUl@{Z?fAC(4mU;K%@l7fYlj9L4 zf^l5iSJT}(9jEs$`yq{kDqldd3X~9TCbo%->Cixft2$RCw808PQTljZmTx%g$!r_* z>-~k5i{o_MW8>S>Y)p;rqo?nWs+e0j?&MRt2I3G=92_TcA=wO{*z`#eFIzq&eT=Ym z`JSRcBX4D`a5>$}E`~k1e$bkF$*P2~>I$uk!Q4^wwPx<$gNj;W9|DdQBu5QC@*tqU zujl+t74aW`%I4Q*RL`%d9`zO5emz4X3NTyLEY4Np}g)KU1m7#KhT$|@XC#eP`-&s}a-7Xf$jbMa!V#Zvy9E4qBs5be73 z_tH4{g&RuHx`>U+4KC6+ixn-kNy)gDUBOIx}c6 zmQqp8?f&i|B_5zUgoZJdtVpkBLn*HXOaM+)taWfv2zt7{0u32z-jEw=a@(Gb>hLQK!mz7wPnzBd5^de)JQW z3T-^arK%I4zYrBZnJswoH(}u}@8_7oG$#4G3cfO@Jk#luWi(5IWp-nNQ?ulW0!{Wz zB*$hm&B8*qe7dDBF-7nA!qPL@;-;w4AlC>MwwS_*s1fI%b3(l zibv$%kx5!ymA-vDAfZBafEGvo*&p~Nr|$4XButQ7QUZn z<1sW+MSf)ByfE5P5c@U&3f(9=jm`E^B35YExNDg%uWgCY&q=By88`PWrx1cRE}F&q zv%HUfdM>z4MHh;`RZB#)<8I-OZV|lXut*m>dw8{D{U=*v3o+aR@;&TXOYonT#7ea( zCDZ>FF`0V$=Io9K)k$%7gm@jX{-ms>Ik;~P!sghgA$zDfvKhEkQ&b2;XN?&Da7^_m z5oPr$vgs#gJ=Xu?ONnIt`Ob~;D^ynSNpbBdm+eso_xEl6%y$_)0bdks4APW))cxb~ zb%x&aQg%j0xYxVvL+l^55qC@WaKwhEmz_Oypj0{FE0QU=soBqz4{m;&X%}(Z|ErG9 zK-9)Nm;Sc(bQ2qxBa!t|ij?qKW2AfX5UaCKsO>_1kt`|6>yW-Y{uG|Gym34CxL9g^c2$TQuJ8*}x15{Wc-eklm`VfG!*a^QmH?X0@ZOj3XrKJsbkeoVMOx z`cJeBra^IvaV^0CjwbsK{$93p<=)HW&Ef@)EMd6?W;?a{1+k``zBOTW5zj-A;@Nlm zaO+-@G39vZUND~==_dke4_~@j-_Vlwn|Je}?s7()Fc+)+_ib~k4rrMYTd=BvkAGeFaki!3^=<6PnNBS2 zQ!HucOtUh&$tcX!_+8{gsr?=Ew)hd5Rqmbx4Q}=&0D3@SjWIAv$|XEaI2d;?unL^ofqrDmr~jw@Ev+#?i*P)k)axm}pKGa3z;nAdB zAS=-g2PId}r5}$2&rE5?G8a;^$f;n>=B3NLJ z04X;!b-W09^N~ERMtsfvFIa3ERREn-@Lc^y(57ga^K)1A=dz9ATclQ_Kn>h;D-==Y zR`?K9lHP=e-%7@&Y)m~Zk~WP$>e&%HCO@8M-i=J}@4hUMq}SZ0?HX5$d)br@`uxrA z@hY~CkF5_k1l?W|3fCI74jU5}FZs46;;~#7^gr&Cv|B4Hy4uo zgd+X>Ufa_Nf`5>rb8?p97G(96NRc{UhJBt?SCA$*>!*qtFA~~a%lr6}u4-6?MSV-N z!teE>dvuR@vWZTIg9}IwvmMb3D7mOw+rrX;=AHVbwU5J(@Ri@wa&@72Nhm@Yy zLR(^Q>}$zvz{jZ!PyUzpj?-;Djt=^4o!byjKkR!@9U{>g(C zx8IX_F%5p@e4Xjvs~f1FYZ`(@NQutMhiA{a@_gyit7Qurvh$McSz{;krot+6NdI!| zm0&$wqvsaROl%Uj)9L(eZU-3W(Y$ZHjOOHvzpt5GDc`V`etJlw4GqY3^7(WKv8>6_ zK)7IDCmz~oS|xL?#SNnrQ8vplbsS^_Qz?W{hrFIQEUohU>{pH}qOhZ74i@XwlvOo3H@yQ9p$X9ORO zX0Wr3T0X#p+okeRi3!;JmI2`Ojb$IGBVnyA&0n0-kUl?wMb zL6tG>(d&-gQb=i>nbVauv1zR~G63F(@ zo$EpX?vJq2E5!S^SPKM~nNxh#EF{={bwt z4D8+COVL`SMu(wl@H#jC7no)5!4)FVpvVyjgd00);3G|>kxOG-cJVjjD}DpXflmAQ zVrz^T#+skx?38~l=J+OwquT2)H4Rk5sO+e}Uz`nL+o&-c0L8||srR)jcxX6Xg;4F; zGYTa9S|HSkbwNmhMWGMB*2NBL!CbAWmCc)(n5hTb#NR{oO-rI>b21?HksHjp?#ETE zqU@~=6{8R)r=?p{$fU7T3RU$9Z{t7t1?hVkE_v@ia41A?6$ak0Aj4|op1RWGeRhG) zOTzSv$0>~d)>ZtV3J!j-C*Z5;tuJ?+$bBShkhNCOn%lNkI6`lc@wt(2W4;0VFzrbf z({XnF#p}-`nWA)lQNoJ@JwGI$0M0$CiZx9TMZDf!ex6a>>+6Zf(&U6G+<QhCcQfeIX6RL(D{hpE?zWm-lr(=_#oJMJhODXHnbQfDI4no=rZ|-<-BdnXEUa={M5{79C1c{#hG zz4$Tv%FO|eed^VH`Bld5nZ#AVkdRZ5^vuwR%jh^Sfjcbe_ct!XcTb+aW?m!yxTnN} z6^&~a#C7A#Rx&c=q1px2X$3VYkM!RPcgZXCkVgm33wALnAZyw@Vq&Gyq@TRN(djni8IIgs zP7(L|eO-8L+1-h#Wk94db}|Z8_ed8kK$yaaV9srmNC1MvG9B)^ntrL#x=gpvLs@7y z^`gY8ht;!>$a4%OcpAgC+ab3-rT}rNo*Qf;bjwhExQ#c(oB3beAaM&0xr#?Y7kzQ= zVc^@a^os-d&E11K21a)x-d~A6AZyyA+$uqyXN0ojPfFIj^`-ZccT@}hUYK~xTA;Z9 zX6$Jg+QGYn&j|PO_-P!UDUoCRpsy(i$;1sqh_BkiW`Z?d$mw zC$Tv_6qM=5Sp zoSd>jV@OcM?R%!77jd)0XdS!2pn`;ByvsUlyBqUG6ti! zdfoA*j%Yp8|5xnfF^w%u0o|H&Rl_pSk#Z&_MO#{XhRb_ea{pDt=Rfk+Y>)#K+p@_y zz?t&;jO&%W2*1~xO44GCX*jCo7u<_h)U^VMFh}{YLFKel{Fv0|m2sQpjS*z*+T`*3 z#;LUV4UTNFqvOOU^e6qGWrK0vI10!@)!5Y_tWlj z*0D7PDnU)^|Q=kxBnRkbxoD8-us^m1dlCZDN8 zotPP~uCx_k)MhCNjkVBc*O#^K=Rlkk*=3pyZalAXSQMMA8c|B(33pZeYm#1cDN}PM zl)Dk^X~6U0nJT-$4>2aiZM0kACcQJO?tTIt)d<~GTW`j;Ud?>$E9_}r@`cqFc8F0* zYve88`a1bN2T%<8M&lT9NH@=rJ*DmUO|uG85-;we^160L4@d!eyY82)*|p`GS?t=b z>GiE9>IE%k3zV3vOEOnQDdn%oXO}fKtir}$Je#=7g48Y_5ezVkSD7sK5uQ>_#gI*x z_y|99>lvd0CEHh=r+wV%=l(`5&cjcOj?>f&UGAgtA>@}f_l~O-8ndmn z69UR&2~8Xd6c*lf1}6o=#x++K#6@3z{1M4zqWLa#E+cztXx;*UkZ6`t7aYhb(d0_3 z;hL{OaiLZjY6=(1TqCk7u_unrW2bQEM%SicxwILLD_y?=U<=+8ipk{gH+_n6Kv*%f zIPUT(9-&qDDi*fC9^Er`zr&E{Q=UCHF&~e6cQ8bb{_(L}dbK&#SkXjbM8O7|!3-cu ztsDh5<3ObXVd(nFP2=QYMnw7a7!EiItEZ(`M`(5}?lq(uU?g!lg$qJ<{C2e-4eC3k z8YCR57V(#GhsteKjrqoAhM>0d&mYfYl{ua~2n`4Ct08(CD`wVKlT*7OVRM8(10W|K zMh6qpzoT?A*1LW1-zeLDw_k$}`UQ0xsD-$`W5W9TA1~{aFjHUWfsiR!{UaI2azx&Dng_ z5Q5#Rt>Dk31d-4{U)V8ty?yk&AL$xD@UiEuxc|f&Swo2do?* zabV^-rjSfEw=^-$|6@pR#a-8W#@rn%DC9Z!K_RSna$|EM%k-0Y8rH@K`Zn_n)^G5c zVPC(HS^N~FE&xyW*|~c$=|{{jtC0R;C$jeM>zUi8WwPNfyo%cTi;bUJ6e=YNGtD)E z)aVQgR1#PT9r3*>u)k__TkP+qJPakG8YqZtPIGH@)o!P3@S=&cC-y^cJG~-y=;mi; zomdcpzky?%?*imhlIQqG8viSXwEhv@9wCRf(LYJ#Us<-nyT=${AT49(0}j z2X@nV{@BXPKQR{#egy+@J_~kr(=aw6Ko|=!>0B(F^lJFL5 z{}h9qYO?Az#!M*jX0JW3Y;2V?GXUW9^c@oJf!l1|O%3X9hB{x<4(^%u8?06UWW6`R zL;QS^%gW8z$)4(A&AkV*uIs0GcwA zzYeXu%P^N9_$z4^pB8A&kTXZvrd$GZnW&4xS&btdkIhW$n9U|1EjX#3vBryL?y*sy%(Z-<5vaTvYq5e3y#JSG+`hTkwu`#Mhvrrd9ZdYevVE zxv)gEpgEak){Dn;u#dDR45f#K7L2Ly&RsV&U=opK%pkNoDC*M2q1MNO9{a+CqUD!yulvL9q$*_z zHz7yf)pfEkN0s*^qTjl4@%3AhSiqEVrLP0Vg<_Dy2o`l$$ddN zk#Yx53LieIgBE%^yyHhZG$z^P)iwH>_;Z*M?%_kg`yfnsdx{Qo;}m7itQnZyi*uGDI&C#pVSSv}8@d`Vri&bvq*B=A z9MD*)R9YSCPlj=VJVlx^R-m`cFWuCYUiwUDg%4FNC>rW@SmnHa4#`LZht2Wq?ImSx zOwRQtrrVy1Gu|~Qd2}HkNH`hw*)CCRY7ZtI2f|>X>^#%W0Sp=Wy2LVcoXEn>b0lGb1kKO!kCJ6QfsNyLCH5uF%wM+^3pm4$Od zA0r*X{6X9yd+;2$z^hesAWf4NCN9jfCI~Q@%flq%D0dsxP+_9wR;YxLS7SnwFqeX8 zZN@onM%*|FJZ&;R`u2Ngp8d64d^k27z10J=YQ*alm;^qnnwC7z^Yp|VKgZr`m;_g^ z7{$&kIv#z=GnHq$`-!bSl1PO}+-ycj8tJH;s2}im3^lYrb7pI-pTGaGLU*4Kjbgd( zz#(duKX_TMBIun2rK;h+w4Hf)^V6mnq4_0k=h`E(07Q+-{>I(FZ$Hv%<&u{)>5usK z?_Sbc1d?85NdSaPr&gZY3GRuv7y{y*j*_-d^v>w6ORiTm=*)6P_l}MJvIFy-mm$0C zcks!VFP8`MV2Bm?Cy9(jQH=?^X3RkeRVN3PQ(XQ4uDCpI=Fnz*9pCQ;9|wY6owzoC&iF8IY+d5Cjw7rDMNSe16yV`4mOpSu@K# zGblEEVm8SQ{RW{@R%`UK$%i^2mTU>aS8;@g=))No%P7nHt(^0Cb%#J_(NLYTq3AON z)Ury|BZk~fU6;_@l(tAGKyDi=I7t9b|47WI6dqhYo+lV!MPn3%p)0+S=5L#ym3c~* z4S&_|GS#N|hGb;-O5C|im2&C!`?B_Dxa(t#eJ6NM17|T-{@#m<3OdIShc*_O3z9di ztgRnM@_UW#dTmZ&Etq*~1RurY7{V!;DkP_2wH)(;XvAbleZM2`3tF`^3H+|0{Nvv+(6KJ1EaQgAfcQL3ZX~LQzUu$V<_Hbda9yrFZ zfV{m_=*C7Kqxr(%t9ncQx5}~`pasiAzLM*Skh`@3)KqD->QmJW@qKZ(AD8c~LL;tz zfo+||aZ>nX_{zXCs3KB9*}8E1Y*1Lj&$%pa?z{GfjLol_(N)^a5734K^a6P-2iJE4 zRj`L`^73({1Pd^&msX(A@vNicDgvaux~SUu3)vnp;Ad?Mf2_q7)3<8O{#e6X!F4|w z?MfRw1z6pDzqE2{0dqjr*{h8Lg&QjC8e{q%%b|pJ?&Gab{e5ivl`A}cu{Iiw{9HKV z2w6N2j20OETx@O-xD>Yud(#-dPW5;}EGD;Z?d6i@^sf+3eg-O{6{PoQAOn`kpmAyh zjH9XjN3@n~H-du!#&#&&GtXhy+cp2GNQF(<(c;)Jt&m&9L#`KG%ywalLmwNTS(M(` z-V8lWMSBX+b5<~c>sQAlBh*JfZbL}9BM%gWFU4V7z5b`Ii7Q$6bnIU>@hIC{d*15q z>V8!<%OY#nQ9}Fi5A9rI2@20w(Q^gvzHkk%Xl26JQoxOmQPn5?LXk_BegYPjytK#t zRmygAlz*PM@n4!i_eGoItW8YYQHct^+v-}ElRIUX&G# zPcD{r^e9UIlzZ}cKJSoO^kDn)ng^@zh^Vyh(Q#VSi_*aRp-mgSqHtps2_ScFV+%oN zsN)B4(>F1qo*64xH`tkK)6x(8s`wv~(#Dy1e^G_iANUFa!9sv|{egL|Rz#jMCmLob zJM5Q{4>m@NNsJrc&qLH`(0OS7xjKDj$4R84x@tM2y+#^aBN$}R&Oz0zQM#RKJ4M#S zbgPS&ZWxpBKw#d@Go**oQ4VNcr3G!qcTAcpUkx6acsV11IJgrOWpEFIPT}2@YKIc} zB+{Vx7F5}e29CV#XKldVBY%XOz9*LX&4x{{5>|qf#OJJ-vny)!T$4}MK=0-saW}Ny zbtUURj`_IwLHM#5HVpS!UX-CX3GftcHt3wH{R;O~7#iN>EqCxo;GB=L@|#Ce%ZX%n zpaIu(h%f($w#EPx$!)1+f=5yyEtZ|q`Ta=Mgfp-=%@xSfG)1dxQ<#^?fa~XLzCmvO zS~*}w=NC5%W6sR9?MyGVHO+jk|I~70x{|BCF(|Xjq=#3?W|6*xTM0+E9vZ6(TA@@* z^VnBHmU3Q&A9JU?G1=ZFJrlnfdD23RlLqkn&bNUCPXcrKP|l*Uxs%?G`+QA`v!l~a zsu9=g-!+fr1^PMVUsjSUOWK{`*zpyPt8x3QE0*_%z9UO4$_rA;aME?J$?a&qG7jAP z-CZ61SauUp6IwA?w(}W-oF+8E0g%W8AP*-wsqw65mx8Az#xa1d!y)Nv<$l6bMQnWf z1>XT>XzI$`{wxoA6gRy4fy6*;EmeT*LF=lPfNA3 zN0Ra9W*DT;rtv)!{wS!j68>tT@3(S~;HGDDYYMQlqOiEQU`q=Y2c^DBk72GEtBvhP zumvyp$2Z~gZ5_Qn36{ypTGz8NH6-Zf)_KOM2xeTRH@gO`QbjcSZyN~%fqGoV3*@Ud z>Tf?RtA?0UMWbxMF~PFwddSx?yqYZ^=7*R!3t?c5@rakUQnfUtYQ~Gg02DXjUSH$pZ)P z&95Ebmf=Oa-J8S`_tsPzj|-LMOjBMTol$T0#oKcPP5OVO)YymEVp7*$F#5LM!|DPK z&9J36NK@!H9*6H&qcfw4_XT`!^znqX58nz4%;UeC1u{$BY~ ze4vZ~ZfO_`)N_YALpL5rS_hD~8if3L+uuIy?;hvBbuCYzh&?k1vTxJSiPfH+Gi^~6 z`SB*lj_2@m6_W~NL7{?afofoDviEsD)m!F#%H@jUgN<1Qj9*g8bRqvMU2Imm;Vxr- z*&hr%3QVk^jDb1o)l50Z4AnGg{#9Rpe>KHSN}BmtaW_1ksp_Her%wz1H_|V9 zS4Tdb$|J)4HxXF4O5;>BYtCEkB2i90?FpV(!`gYVL?`(#_8nE{pCKPqY8B2_5PR-x zBN4$0bz=nCRcDQ^!R6)#S?-7+udQo8E^1^>qL-fmt0CJxD!Rw4bO8NgZla$wG}It zXT~5ac%y6AKd{;v-nb#do5z9C1;@s$MJR}oc8W5YQ5lR6$AquKvOj{an!-4YvG;!4X%1&? zES`r^-~A?<(#s33nLoHbM6kQJc-p_X`l$2-+DaE?KB~ly|8)GUzOrfZ-2`Wh4KiVP zbW-HN@U?RR6WgfGSGKB@8((-{_cSwP4jev7zT5K3asjroJ0$d3U`=7VN|ZpmyQU2@ z0;oc)_~^f3gFE0ku7{VRvrqdG!;96wiL=hdBmn z#U<34wkU5_od>3^rYcH3j~V?aDNqS_3|j9=nx2KbuM=-Zd?Y-IA&Y~UoE$P=_kd}y z+4J+Vl`x^#p$y;i%Q#-92)^~YnM=zY--BV$9ARFaIHQkZY@?ztIkvVRxq7w_$L~XG zq9!Gbs=@Dg5?dBRO0}#e&8BtfQQYQa)UImNU{X zQ|*04@|*l6H!U*O=(a~By(|BSW=7C)T@^IDavGf#H(^Z{lg)Db>}A%44t2gpa@OTn z1MYP044>l!%)*J;P2pZ^jFGvFj#?lgNn^nx#P~D;q%@COi2&ca3y5z4bqtb4;2#kI z6tUV*;Qy}@#q--2HA6%bOGdu+3)Y(3UB71iI6O^sxm95zxVhW^JTHCj@L1{7C-*|S zvtQusI7*nmFchfhLJAmQK(`WI?=71Y*PK{X^P2sfhNGjp`BrHZ_@?SjO_G$#7aB4G zEAmvmg%kGgZWsnNLm;kfQ$?}jn|v3gSD(d^YfqK$Ws?cGC4GneJ-qWo>M$*X zm_6c>kHC+S-UnfKd($=cIo9|IWUJ<6Z3#|O>3>>HVJGv*=ITf(+r*6|v3l>LdVA5( z2fyRbf)E6j*-J%Z3pI&g0etHaZTJmj5SSz+8~#VI3IJV(cm>~dvgI(DxaM9Oj;bC? zG^{hU5|93j)LR~FR@i053@7^u=FMG>9tSG-hs3Z{PXZYzbir%{)5-5+t_0UyylPhh ztfCWl9aNk3GsDlB(ctroVz%DdjdQff=h~ir^Ddjya$*2YAYmbVmD|kxc5`*L)wEk? z?Ti}PZaFMubeIh=JZ?{2k2Lmt!%fYhx`x1m+<~Dm1!s98|Q;s|MrG2ews}k9?(n%T>W71NboI8 z``FuQB>^Xf0;6wNg(gTtJ1b@3^*PS>#2>%9$I4}%Fv2k|%WZ;_O^l3)`;htftCbno zyqK6jY8!rz|A^QL)_a&ES$RJ`J|*P)4*JI@#XSt^o0~z0d@e2Ys4~k6RWg~^#rg)$ z^2R>D>d?XJ4hR5B`h|nUOW3G$i2)P-v00b_nY(j;HviKyw?eblw*%!C^jB54E zgkH8j?`Ql*c`9uAYl#yWd=HfUA)RHnci9r*Svt)5dyNrGGufB#p${V5YF7fQx}vfR znRya)Y=DjJ?V;-t1IJWD?b1L<>@W^iZX4hJ=|@@6nAK<@u$U(sxjFG| z?P!AYQu8JG8LtJ`E^ZGCg>e{;ejg*qlh5^}6>N(;3Dh~eeSO25Q29QloT8QR*RXW> zozRQ%=ujI#f#H6N!b>4mIKIGs0kt%zEH144Xue; zFVQOa`($D}Q;6!-cN17lcUyyvj~`pXQC9lw^|0w0K(rm{0ti5~ofmd3t8sTVzB@Ab ztB1Q(b{479ZxqC)3f{^r7ZvCFa;hDgNTL-HA0k-lg8Fp3s2|)2@%GD zzn)i>#vrO})|KzK%Ya}#y4rQcChz0Af>Z$qmvmIKTK>XzD-EVmDT89&$gs9*xi39G z#ALt~XZm6K{VqAf6P=s=WNMmELkm$ zYe}?|{o#;jCK_c`{piGNLP*c<0= z_GWb)thmU&MSXf)A9zHcYH+@Ug+y9*W%EsVg9OPa*g==YF4mP*G-RgqzCsVehkW6} zH|ClaGl*=zt*1{dyEccRwKX?Wc!#f-A;1X3Rwp?b>a?#aYyxMxs(v%_4sdUUiN}W= zt>ti{pi1i=&#wLRswP*Co99itE)}R3wZFabd)Z%Y6Z1D_vpYe)c%XB4v0|~w8r|t=OMjP>~f>0uJka=XA=@5#7_PZNDQv{7GX{)OZal3Uo!7& z%kZI4_3sxV|A<=dJAZrr)^y4Y%e;&ek|-*EWiaGz1y za0-{G4Hq7oUo;zzuy>)}OiLH1xz*9jQn)t^%;DR^fj0s62oi-PXk$%W_XkcV4&i9% zyVjtN^ZH;R^<_LhBedakcJyS3?6#${q_Q9QL z`ST1S{sx#=OE|lXY*s(_xi0?;#=IxpJ6?_P8PNYjP{vx2Ey|(gOZ>pKLKy?`OiyZA z`a(Y4XeW6+u#A@qS>erHVUzAS%jU(GUogZKneU|dEYH<)_ct`g&hf7=3HjEZR3Slc zlG!a@-5h-5>8hL;kIw=V=*Y}a(~{6d%eEz=1|1)q-$9wwj@x`t!V8)4ADR`3{m5AF zSTE}2WO67|V&5Pi3ZNj-7p_r-1%eB;=tATaCG|B zr=B1wDtv}9hsY9Ken|Iy!y+#2T$US7VrAv=J}PgdqeUK9jn(+v$^j$OjOq+#kGiHN z+Z8s|naKZixG(o<&eF+Zl9JLqrYga!WsMEL8NqIK#|kc<^=EnXIy8u-XJSO z^rnLav=~xv)Ye+=M~Q9p*e2*VF!+HLez9gEGT4Z2Cc@iG5!IfoF;H~n1=J8h2!Hic z+g(u7`urrJ*C>4W*x8kF52N8N^7ie9D(_H&^bhF_1}02kckdE&@l}rJ;t*Udl>_r0 zIIYa_!^P1A8oKV2-H{lG!>7;0Jz1jS`>iVko5wlGGV$5-tZxBp>3{#veYcEY1pGKz z2%M~po|KqFA!DNZ8`)Dhe)gWdFp=7`+tTX5=HTgT^EX97 zdDQWz@G$sFu_Yrw?4b}j>tx~h9LSi9Ah*~yQ5@){C&V~38kYGM&A*Wt@YlhXm%(Pe|J4<_J9y^08&OHKv8 ziW&X&u7aXN@jx4z9fO(W5Y^RnozoJeEf^#y<3}%H__{UU5Xme?)3Ij70u3}3HM~P7 z$kR%sYs}nlE;{FxwgYC3>)QWZVH*7WBcOs>ug{VLe2FiEqlQ#i#cb zROVC$WKcJeu2sRZZ`GpbzR`13YWK2(=SCQd%p%wdj%Gm3b}H;z(xd*js(7jafBz0_ zkD#(p?1?KUyb3esOrOoTd^c3hIx3+rLXr0WSH)PL?jK+-rANRN(!PFp{l`L7#|Z5j z63AB~Qt0blVg4q+wb0eEgx1>GmZ$tdv*9eOzfJ=Mh8|Zt$c3CnazOMBm^N2%QL+TS z>jVwfVB+Uud$#pESn=;N@-Qk`aEAr)CD3mbbr04cu_yxB*A$)FWa8069v4X*)Siin z%bQ!Co4(vX%I_Jh_@;2C-8$hF)fI`+qScI?=h1J9pLmkV-u>o&z$c2}Jv;=MtXGI; zkmFC&ZI<4yan~|a;jDEJCtN9Sgk7vv1H*@kL(Yg_cfcZYG?e+kwz%+8$%!#SDHj~K zl_K-*qc&7bgyzwd1k)SRXKKtl?um&*K6;r83TYeY32XUNjpNC+OXxDyPH}+UrKvlB zLf(VtzZ&N-jx(%>+&3}jnp+4;_^U<6H@o=&OP9tW$RPqrIzE!lsrYLIAoxOD!1jv% zPwF6RKq_CgNgU#Ghghc>_`Pc|(T)*IUV2IyR=~5&GDa7}W-|M%j(Dh(P@C(bG%8I@ zyt&=h%ZP$#XStQ!!+1ClUSdS|>B|FeV@}J%SK-8Xm1_`%iLi#AxvtpTekPxmLQ1gP5TDN7BzLOS-!;84+Ga5X|i?YR%z(qaG$& zeU-6yrq`GFY*bK1uZk{aQ@un$gDZGp7lCnJ-aAJt8XjD}nNZ@<_6`zXfN)M(nIG&K z$KI+W=1KfORQMN|9xkMNmw*63GByVb+Lw~1UYygt=px6B^|U7^f!?#yvp#;i|GdOq zr~0|1S-Lq@R~!S74X6-=cKy=Z%X0R)ner^*Z#CXk_uF*uyJ@Iu}4H2!>EW`3RSs=v@XlPeQ5F{(nWW>i>#jM=*h< z`%SV(W}RKU z=98|6-&Uyn>b{Qi$UqxnoJ$LD&}q24gKnEWUInk#HbV;VK;RP99lR~7rffaUn=G*y z**!7969x5WtB`6=Nvn?pCw22~U8jKm-QE^1eU`~1t(m3AWPhrR-t~%R2OGwqf3h} zKfN@Yq;j=b$cRKtV&bv&cOnr#%09wJEO4Abe~h;8a=o>iPFe8-FDGyA<9AS);gaL- zRjvKKE_}{X360Z;2eex=1=}w|5oa+C{nlIAkFS0PTB6y+)jql21AI=|jDPH^QqW6t z$3u)*S`2w2LnrBLj@sO73X`jha6)ge5b&Yi0XipNODuM; zDU$J|ez=huJOVuccX*>*Ukay@OYTc2H??)XT_v0R6e5?JakrEdUB^KujzF9-B2)&=Sq z|8Go{bIi8mVNvM5s-|qg;@s=$U+3!)wr}SDTQsx(w`l5@Nd9=|7PUaoyUGky#9HcM z!#|v$W-ShmmGLI+y`2oy>ZG4109{p$j6Ty)0Tm$^0-T zcpI3Cx7P^t)ziXAXYL*pi^P!2xPHsz+liAyYSWn|4R=_4uiJnS!bXI{y)8tfnNXs literal 0 HcmV?d00001 From 034eb6980db5405c50bf689b51ad4cfb5d895c89 Mon Sep 17 00:00:00 2001 From: hpinkos Date: Fri, 28 Jun 2013 17:56:37 -0400 Subject: [PATCH 278/306] fixed test errors --- Source/Core/WallGeometry.js | 2 +- Specs/Core/WallGeometrySpec.js | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Source/Core/WallGeometry.js b/Source/Core/WallGeometry.js index 6fba5e364dfc..14c298d28532 100644 --- a/Source/Core/WallGeometry.js +++ b/Source/Core/WallGeometry.js @@ -144,7 +144,7 @@ define([ var terrainHeight = 0.0; if (terrain !== undefined) { - var h = terrain[i].height; + var h = terrain[i/3].height; if (!isNaN(h)) { terrainHeight = h; } diff --git a/Specs/Core/WallGeometrySpec.js b/Specs/Core/WallGeometrySpec.js index 76f714737d6a..36841f7cd15c 100644 --- a/Specs/Core/WallGeometrySpec.js +++ b/Specs/Core/WallGeometrySpec.js @@ -78,12 +78,12 @@ defineSuite([ positions : ellipsoid.cartographicArrayToCartesianArray(coords) }); - expect(w.attributes.position.values.length).toEqual(3 * 2 * 3); - expect(w.attributes.normal.values.length).toEqual(3 * 2 * 3); - expect(w.attributes.tangent.values.length).toEqual(3 * 2 * 3); - expect(w.attributes.binormal.values.length).toEqual(3 * 2 * 3); - expect(w.attributes.st.values.length).toEqual(3 * 2 * 2); - expect(w.indices.length).toEqual((3 * 2 - 2) * 3); + expect(w.attributes.position.values.length).toEqual(4 * 2 * 3); + expect(w.attributes.normal.values.length).toEqual(4 * 2 * 3); + expect(w.attributes.tangent.values.length).toEqual(4 * 2 * 3); + expect(w.attributes.binormal.values.length).toEqual(4 * 2 * 3); + expect(w.attributes.st.values.length).toEqual(4 * 2 * 2); + expect(w.indices.length).toEqual((4 * 2 - 2) * 3); }); }); From 92e55ddde769c50f6dab1d8989f97dbae29aed31 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Fri, 28 Jun 2013 18:39:50 -0400 Subject: [PATCH 279/306] Fix Custom Rendering Sandcastle example. --- Apps/Sandcastle/gallery/Custom Rendering.html | 301 ++---------------- 1 file changed, 25 insertions(+), 276 deletions(-) diff --git a/Apps/Sandcastle/gallery/Custom Rendering.html b/Apps/Sandcastle/gallery/Custom Rendering.html index ba88e62d4d4f..d200947dba90 100644 --- a/Apps/Sandcastle/gallery/Custom Rendering.html +++ b/Apps/Sandcastle/gallery/Custom Rendering.html @@ -43,90 +43,40 @@ } var Box = function(position) { - this._pickId = undefined; - - this._colorCommand = new Cesium.DrawCommand(); - this._pickCommand = new Cesium.DrawCommand(); - this._colorCommand.primitiveType = this._pickCommand.primitiveType = Cesium.PrimitiveType.LINES; - this._colorCommand.boundingVolume = this._pickCommand.boundingVolume = new Cesium.BoundingSphere(); - this._colorCommand.modelMatrix = this._pickCommand.modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(position); - - this._commandLists = new Cesium.CommandLists(); - - var that = this; - this._colorCommand.uniformMap = { - u_color : function() { - return Cesium.Color.YELLOW; - } - }; - this._pickCommand.uniformMap = { - u_color : function() { - return that._pickId.color; - } - }; + this._modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(position); + this._primitive = undefined; }; Box.prototype.update = function(context, frameState, commandList) { - // Only supports 3D, not 2D or Columbus view. - if (frameState.mode !== Cesium.SceneMode.SCENE3D) { - return; - } - - var colorCommand = this._colorCommand; - var pickCommand = this._pickCommand; - - if (typeof colorCommand.vertexArray === 'undefined') { - var vs = ''; - vs += 'attribute vec4 position;'; - vs += 'void main()'; - vs += '{'; - vs += ' gl_Position = czm_modelViewProjection * position;'; - vs += '}'; - - var fs = ''; - fs += 'uniform vec4 u_color;'; - fs += 'void main()'; - fs += '{'; - fs += ' gl_FragColor = u_color;'; - fs += '}'; - + if (typeof this._primitive === 'undefined') { var dimensions = new Cesium.Cartesian3(500000.0, 500000.0, 500000.0); var maximumCorner = dimensions.multiplyByScalar(0.5); var minimumCorner = maximumCorner.negate(); - Cesium.BoundingSphere.fromPoints([minimumCorner, maximumCorner], colorCommand.boundingVolume); - - var geometry = Cesium.GeometryPipeline.toWireframe(new Cesium.BoxGeometry({ - minimumCorner : minimumCorner, - maximumCorner : maximumCorner - })); - var attributeIndices = Cesium.GeometryPipeline.createAttributeIndices(geometry); - - colorCommand.vertexArray = pickCommand.vertexArray = context.createVertexArrayFromGeometry({ - geometry : geometry, - attributeIndices : attributeIndices, - bufferUsage : Cesium.BufferUsage.STATIC_DRAW - }); - - colorCommand.shaderProgram = pickCommand.shaderProgram = context.getShaderCache().getShaderProgram(vs, fs, attributeIndices); - colorCommand.renderState = pickCommand.renderState = context.createRenderState({ - depthTest : { - enabled : true + + var instance = new Cesium.GeometryInstance({ + geometry : new Cesium.BoxGeometry({ + vertexFormat : Cesium.PerInstanceColorAppearance.VERTEX_FORMAT, + minimumCorner : minimumCorner, + maximumCorner : maximumCorner + }), + modelMatrix : this._modelMatrix, + id : this, + attributes : { + color : new Cesium.ColorGeometryInstanceAttribute(1.0, 1.0, 0.0, 1.0) } }); - - this._pickId = context.createPickId(this); - } - - var pass = frameState.passes; - this._commandLists.removeAll(); - if (pass.color) { - this._commandLists.colorList.push(colorCommand); - } - if (pass.pick) { - this._commandLists.pickList.push(pickCommand); + + Cesium.GeometryPipeline.toWireframe(instance.geometry); + + this._primitive = new Cesium.Primitive({ + geometryInstances : instance, + appearance : new Cesium.PerInstanceColorAppearance({ + flat : true + }) + }); } - commandList.push(this._commandLists); + this._primitive.update(context, frameState, commandList); }; Box.prototype.isDestroyed = function() { @@ -134,196 +84,13 @@ }; Box.prototype.destroy = function() { - var colorCommand = this._colorCommand; - colorCommand.vertexArray = colorCommand.vertexArray && colorCommand.vertexArray.destroy(); - colorCommand.shaderProgram = colorCommand.shaderProgram && colorCommand.shaderProgram.release(); - this._pickId = this._pickId && this._pickId.destroy(); + this._primitive = this._primitive && this._primitive.destroy(); return Cesium.destroyObject(this); }; - function renderBoxAcrossModes(scene) { - Sandcastle.declare(renderBoxAcrossModes); // For highlighting in Sandcastle. - var primitives = scene.getPrimitives(); - primitives.add(new Box2(ellipsoid.cartographicToCartesian(Cesium.Cartographic.fromDegrees(-75.59777, 40.03883, 500000.0)))); - } - - var Box2 = function(position) { - this._ellipsoid = ellipsoid; - this._pickId = undefined; - - this._colorCommand = new Cesium.DrawCommand(); - this._pickCommand = new Cesium.DrawCommand(); - this._colorCommand.primitiveType = this._pickCommand.primitiveType = Cesium.PrimitiveType.LINES; - this._colorCommand.boundingVolume = this._pickCommand.boundingVolume = new Cesium.BoundingSphere(); - - this._commandLists = new Cesium.CommandLists(); - - this._mode = undefined; - this._projection = undefined; - - this._attributeIndices = { - position2D : 0, - position3D : 1 - }; - - this._position = position; - this._modelMatrix = undefined; - - var that = this; - this._colorCommand.uniformMap = { - u_color : function() { - return Cesium.Color.LIME; - } - }; - this._pickCommand.uniformMap = { - u_color : function() { - return that._pickId.color; - } - }; - }; - - Box2.prototype.update = function(context, frameState, commandList) { - var mode = frameState.mode; - var projection = frameState.scene2D.projection; - var colorCommand = this._colorCommand; - var pickCommand = this._pickCommand; - - if (mode !== this._mode || projection !== this._projection) { - this._mode = mode; - this._projection = projection; - - var zLength = this._ellipsoid.getRadii().getMaximumComponent() * 0.1; - var x = zLength * 0.1; - var y = zLength * 0.5; - var z = zLength; - - this._modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(this._position); - - var dimensions = new Cesium.Cartesian3(500000.0, 500000.0, 500000.0); - var maximumCorner = dimensions.multiplyByScalar(0.5); - var minimumCorner = maximumCorner.negate(); - - var geometry = Cesium.GeometryPipeline.toWireframe(new Cesium.BoxGeometry({ - minimumCorner : minimumCorner, - maximumCorner : maximumCorner - })); - geometry.attributes.position3D = geometry.attributes.position; - delete geometry.attributes.position; - - if (mode === Cesium.SceneMode.SCENE3D) { - geometry.attributes.position2D = { // Not actually used in shader - value : [0.0, 0.0] - }; - - Cesium.BoundingSphere.fromPoints([ - new Cesium.Cartesian3(-x, -y, -z), - new Cesium.Cartesian3(x, y, z) - ], - colorCommand.boundingVolume); - } else { - var positions = geometry.attributes.position3D.values; - var projectedPositions = []; - var projectedPositionsFlat = []; - for ( var i = 0; i < positions.length; i += 3) { - var modelPosition = new Cesium.Cartesian3(positions[i], positions[i + 1], positions[i + 2]); - var worldPosition = this._modelMatrix.multiplyByPoint(modelPosition); - - positions[i] = worldPosition.x; - positions[i + 1] = worldPosition.y; - positions[i + 2] = worldPosition.z; - - var projectedPosition = projection.project(this._ellipsoid.cartesianToCartographic(worldPosition)); - - projectedPositions.push(projectedPosition); - projectedPositionsFlat.push(projectedPosition.z, projectedPosition.x, projectedPosition.y); - } - - if (mode === Cesium.SceneMode.SCENE2D || mode === Cesium.SceneMode.COLUMBUS_VIEW) { - Cesium.BoundingSphere.fromPoints(projectedPositions, colorCommand.boundingVolume); - colorCommand.boundingVolume.center = new Cesium.Cartesian3(colorCommand.boundingVolume.center.z, colorCommand.boundingVolume.center.x, colorCommand.boundingVolume.center.y); - } else { - var bv3D = Cesium.BoundingSphere.fromPoints([ - minimumCorner, - maximumCorner - ]); - var bv2D = Cesium.BoundingSphere.fromPoints(projectedPositions); - bv2D.center = new Cesium.Cartesian3(bv2D.center.z, bv2D.center.x, bv2D.center.y); - - bv3D.union(bv2D, colorCommand.boundingVolume); - } - - geometry.attributes.position2D = { - componentDatatype : Cesium.ComponentDatatype.FLOAT, - componentsPerAttribute : 3, - values : projectedPositionsFlat - }; - } - - colorCommand.vertexArray = colorCommand.vertexArray && colorCommand.vertexArray.destroy(); - colorCommand.vertexArray = pickCommand.vertexArray = context.createVertexArrayFromGeometry({ - geometry : geometry, - attributeIndices : this._attributeIndices, - bufferUsage : Cesium.BufferUsage.STATIC_DRAW - }); - } - - if (typeof colorCommand.shaderProgram === 'undefined') { - var vs = ''; - vs += 'attribute vec4 position2D;'; - vs += 'attribute vec4 position3D;'; - vs += 'void main()'; - vs += '{'; - vs += ' vec4 p = czm_columbusViewMorph(position2D, position3D, czm_morphTime);'; - vs += ' gl_Position = czm_modelViewProjection * p;'; - vs += '}'; - - var fs = ''; - fs += 'uniform vec4 u_color;'; - fs += 'void main()'; - fs += '{'; - fs += ' gl_FragColor = u_color;'; - fs += '}'; - - colorCommand.shaderProgram = pickCommand.shaderProgram = context.getShaderCache().getShaderProgram(vs, fs, this._attributeIndices); - colorCommand.renderState = pickCommand.renderState = context.createRenderState({ - depthTest : { - enabled : true - } - }); - } - - var pass = frameState.passes; - if (pass.pick && typeof this._pickId === 'undefined') { - this._pickId = context.createPickId(this); - } - - var modelMatrix = Cesium.Matrix4.IDENTITY; - if (mode === Cesium.SceneMode.SCENE3D) { - modelMatrix = this._modelMatrix; - } - - this._commandLists.removeAll(); - if (pass.color) { - colorCommand.modelMatrix = modelMatrix; - this._commandLists.colorList.push(colorCommand); - } - if (pass.pick) { - pickCommand.modelMatrix = modelMatrix; - this._commandLists.pickList.push(pickCommand); - } - - commandList.push(this._commandLists); - }; - - // These functions are the same as before. - Box2.prototype.isDestroyed = Box.prototype.isDestroyed; - Box2.prototype.destroy = Box.prototype.destroy; - function createButtons(widget) { var scene = widget.scene; - var centralBody = widget.centralBody; var ellipsoid = widget.centralBody.getEllipsoid(); - var primitives = scene.getPrimitives(); var transitioner = new Cesium.SceneTransitioner(scene, ellipsoid); var sceneMenu = new DropDownMenu({ @@ -351,24 +118,6 @@ } })); - new Button({ - label : 'Render a box', - onClick : function() { - primitives.removeAll(); - renderBox(scene); - Sandcastle.highlight(renderBox); - } - }).placeAt('toolbar'); - - new Button({ - label : 'Render a box across scene modes', - onClick : function() { - primitives.removeAll(); - renderBoxAcrossModes(scene); - Sandcastle.highlight(renderBoxAcrossModes); - } - }).placeAt('toolbar'); - new DropDownButton({ label : 'Scene Mode', dropDown : sceneMenu From 2bab3ce88c6e671ff18c31dc2bba947d6f355a63 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Fri, 28 Jun 2013 20:15:13 -0400 Subject: [PATCH 280/306] Add tests for new BoundingSphere functions. --- Specs/Core/BoundingSphereSpec.js | 87 +++++++++++++++++++++++++++++--- 1 file changed, 79 insertions(+), 8 deletions(-) diff --git a/Specs/Core/BoundingSphereSpec.js b/Specs/Core/BoundingSphereSpec.js index ad944e4ac77f..fadf7f21a41d 100644 --- a/Specs/Core/BoundingSphereSpec.js +++ b/Specs/Core/BoundingSphereSpec.js @@ -27,17 +27,19 @@ defineSuite([ /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/ var positionsRadius = 1.0; - var positionsCenter = new Cartesian3(1.0, 0.0, 0.0); + var positionsCenter = new Cartesian3(10000001.0, 0.0, 0.0); + + var center = new Cartesian3(10000000.0, 0.0, 0.0); function getPositions() { return [ - new Cartesian3(1, 0, 0), - new Cartesian3(2, 0, 0), - new Cartesian3(0, 0, 0), - new Cartesian3(1, 1, 0), - new Cartesian3(1, -1, 0), - new Cartesian3(1, 0, 1), - new Cartesian3(1, 0, -1) + center.add(new Cartesian3(1, 0, 0)), + center.add(new Cartesian3(2, 0, 0)), + center.add(new Cartesian3(0, 0, 0)), + center.add(new Cartesian3(1, 1, 0)), + center.add(new Cartesian3(1, -1, 0)), + center.add(new Cartesian3(1, 0, 1)), + center.add(new Cartesian3(1, 0, -1)) ]; } @@ -322,6 +324,27 @@ defineSuite([ }).toThrow(); }); + it('fromEllipsoid', function() { + var ellipsoid = Ellipsoid.WGS84; + var sphere = BoundingSphere.fromEllipsoid(ellipsoid); + expect(sphere.center).toEqual(Cartesian3.ZERO); + expect(sphere.radius).toEqual(ellipsoid.getMaximumRadius()); + }); + + it('fromEllipsoid with a result parameter', function() { + var ellipsoid = Ellipsoid.WGS84; + var sphere = new BoundingSphere(); + var result = BoundingSphere.fromEllipsoid(ellipsoid, sphere); + expect(result).toBe(sphere); + expect(result).toEqual(new BoundingSphere(Cartesian3.ZERO, ellipsoid.getMaximumRadius())); + }); + + it('fromEllipsoid throws without ellipsoid', function() { + expect(function() { + BoundingSphere.fromEllipsoid(); + }).toThrow(); + }); + it('sphere on the positive side of a plane', function() { var sphere = new BoundingSphere(Cartesian3.ZERO, 0.5); var normal = Cartesian3.UNIT_X.negate(); @@ -383,6 +406,54 @@ defineSuite([ expect(bs.getPlaneDistances(position, direction)).toEqual(expected); }); + it('projectTo2D', function() { + var positions = getPositions(); + var projection = new GeographicProjection(); + + var positions2D = []; + for (var i = 0; i < positions.length; ++i) { + var position = positions[i]; + var cartographic = projection.getEllipsoid().cartesianToCartographic(position); + positions2D.push(projection.project(cartographic)); + } + + var boundingSphere3D = BoundingSphere.fromPoints(positions); + var boundingSphere2D = boundingSphere3D.projectTo2D(projection); + var actualSphere = BoundingSphere.fromPoints(positions2D); + actualSphere.center = new Cartesian3(actualSphere.center.z, actualSphere.center.x, actualSphere.center.y); + + expect(boundingSphere2D.center).toEqualEpsilon(actualSphere.center, CesiumMath.EPSILON6); + expect(boundingSphere2D.radius).toBeGreaterThan(actualSphere.radius); + }); + + it('projectTo2D with result parameter', function() { + var positions = getPositions(); + var projection = new GeographicProjection(); + var sphere = new BoundingSphere(); + + var positions2D = []; + for (var i = 0; i < positions.length; ++i) { + var position = positions[i]; + var cartographic = projection.getEllipsoid().cartesianToCartographic(position); + positions2D.push(projection.project(cartographic)); + } + + var boundingSphere3D = BoundingSphere.fromPoints(positions); + var boundingSphere2D = boundingSphere3D.projectTo2D(projection, sphere); + var actualSphere = BoundingSphere.fromPoints(positions2D); + actualSphere.center = new Cartesian3(actualSphere.center.z, actualSphere.center.x, actualSphere.center.y); + + expect(boundingSphere2D).toBe(sphere); + expect(boundingSphere2D.center).toEqualEpsilon(actualSphere.center, CesiumMath.EPSILON6); + expect(boundingSphere2D.radius).toBeGreaterThan(actualSphere.radius); + }); + + it('static projectTo2D throws without sphere', function() { + expect(function() { + BoundingSphere.projectTo2D(); + }).toThrow(); + }); + it('static clone returns undefined with no parameter', function() { expect(typeof BoundingSphere.clone()).toEqual('undefined'); }); From 86fc0059c559fbe4aa5b85f0ac2f99d1a54715a2 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Fri, 28 Jun 2013 20:43:16 -0400 Subject: [PATCH 281/306] Add tests for new Extent functions and for ColorGeometryInstanceAttribute. --- .../ColorGeometryInstanceAttributeSpec.js | 51 +++++++++++++++++++ Specs/Core/ExtentSpec.js | 42 +++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 Specs/Core/ColorGeometryInstanceAttributeSpec.js diff --git a/Specs/Core/ColorGeometryInstanceAttributeSpec.js b/Specs/Core/ColorGeometryInstanceAttributeSpec.js new file mode 100644 index 000000000000..ca38ce763e4f --- /dev/null +++ b/Specs/Core/ColorGeometryInstanceAttributeSpec.js @@ -0,0 +1,51 @@ +/*global defineSuite*/ +defineSuite([ + 'Core/ColorGeometryInstanceAttribute', + 'Core/Color', + 'Core/ComponentDatatype' + ], function( + ColorGeometryInstanceAttribute, + Color, + ComponentDatatype) { + "use strict"; + /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/ + + it('constructor', function() { + var attribute = new ColorGeometryInstanceAttribute(1.0, 1.0, 0.0, 0.5); + expect(attribute.componentDatatype).toEqual(ComponentDatatype.UNSIGNED_BYTE); + expect(attribute.componentsPerAttribute).toEqual(4); + expect(attribute.normalize).toEqual(true); + + var value = new Uint8Array(new Color(1.0, 1.0, 0.0, 0.5).toBytes()); + expect(attribute.value).toEqual(value); + }); + + it('fromColor', function() { + var color = Color.AQUA; + var attribute = ColorGeometryInstanceAttribute.fromColor(color); + expect(attribute.componentDatatype).toEqual(ComponentDatatype.UNSIGNED_BYTE); + expect(attribute.componentsPerAttribute).toEqual(4); + expect(attribute.normalize).toEqual(true); + + var value = new Uint8Array(color.toBytes()); + expect(attribute.value).toEqual(value); + }); + + it('fromColor throws without color', function() { + expect(function() { + ColorGeometryInstanceAttribute.fromColor(); + }).toThrow(); + }); + + it('toValue', function() { + var color = Color.AQUA; + expect(ColorGeometryInstanceAttribute.toValue(color)).toEqual(new Uint8Array(color.toBytes())); + }); + + it('toValue throws without a color', function() { + expect(function() { + ColorGeometryInstanceAttribute.toValue(); + }).toThrow(); + }); + +}); diff --git a/Specs/Core/ExtentSpec.js b/Specs/Core/ExtentSpec.js index 77eef180dc22..8c2d55718420 100644 --- a/Specs/Core/ExtentSpec.js +++ b/Specs/Core/ExtentSpec.js @@ -36,6 +36,34 @@ defineSuite([ expect(extent.north).toEqual(north); }); + it('fromDegrees produces expected values.', function() { + var west = -10.0; + var south = -20.0; + var east = 10.0; + var north = 20.0; + + var extent = Extent.fromDegrees(west, south, east, north); + expect(extent.west).toEqual(CesiumMath.toRadians(west)); + expect(extent.south).toEqual(CesiumMath.toRadians(south)); + expect(extent.east).toEqual(CesiumMath.toRadians(east)); + expect(extent.north).toEqual(CesiumMath.toRadians(north)); + }); + + it('fromDegrees works with a result parameter.', function() { + var west = -10.0; + var south = -20.0; + var east = 10.0; + var north = 20.0; + + var result = new Extent(); + var extent = Extent.fromDegrees(west, south, east, north, result); + expect(result).toBe(extent); + expect(extent.west).toEqual(CesiumMath.toRadians(west)); + expect(extent.south).toEqual(CesiumMath.toRadians(south)); + expect(extent.east).toEqual(CesiumMath.toRadians(east)); + expect(extent.north).toEqual(CesiumMath.toRadians(north)); + }); + it('fromCartographicArray produces expected values.', function() { var minLon = new Cartographic(-0.1, 0.3, 0.0); var minLat = new Cartographic(0.0, -0.2, 0.0); @@ -87,6 +115,10 @@ defineSuite([ expect(returnedResult).toBe(extent); }); + it('clone works without extent', function() { + expect(Extent.clone()).not.toBeDefined(); + }); + it('Equals works in all cases', function() { var extent = new Extent(0.1, 0.2, 0.3, 0.4); expect(extent.equals(new Extent(0.1, 0.2, 0.3, 0.4))).toEqual(true); @@ -97,6 +129,16 @@ defineSuite([ expect(extent.equals(undefined)).toEqual(false); }); + it('Static equals works in all cases', function() { + var extent = new Extent(0.1, 0.2, 0.3, 0.4); + expect(Extent.equals(extent, new Extent(0.1, 0.2, 0.3, 0.4))).toEqual(true); + expect(Extent.equals(extent, new Extent(0.5, 0.2, 0.3, 0.4))).toEqual(false); + expect(Extent.equals(extent, new Extent(0.1, 0.5, 0.3, 0.4))).toEqual(false); + expect(Extent.equals(extent, new Extent(0.1, 0.2, 0.5, 0.4))).toEqual(false); + expect(Extent.equals(extent, new Extent(0.1, 0.2, 0.3, 0.5))).toEqual(false); + expect(Extent.equals(extent, undefined)).toEqual(false); + }); + it('Equals epsilon works in all cases', function() { var extent = new Extent(0.1, 0.2, 0.3, 0.4); expect(extent.equalsEpsilon(new Extent(0.1, 0.2, 0.3, 0.4), 0.0)).toEqual(true); From 9007ca1bd7722712465a382d673f7038ea84da6e Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Mon, 1 Jul 2013 16:09:49 -0400 Subject: [PATCH 282/306] Fix CHANGES.md --- CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 75d6bd41e579..110e9a82cf3b 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -4,7 +4,7 @@ Change Log Beta Releases ------------- -### b18 - 2013-08-01 +### b19 - 2013-08-01 * Breaking changes: * Replaced tessellators and meshes with geometry. In particular: From f06712b93b2d65a894129ba46167e7a956ca18a4 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 1 Jul 2013 16:31:14 -0400 Subject: [PATCH 283/306] Add Geometry* tests. --- Source/Core/GeometryPipeline.js | 9 +- Specs/Core/GeometryAttributeSpec.js | 85 +++++++ Specs/Core/GeometryInstanceAttributeSpec.js | 61 +++++ Specs/Core/GeometryInstanceSpec.js | 159 ++++++++++++ Specs/Core/GeometryPipelineSpec.js | 233 +++++++++++++++++- Specs/Core/GeometrySpec.js | 257 ++++++++++++++++++++ 6 files changed, 793 insertions(+), 11 deletions(-) create mode 100644 Specs/Core/GeometryAttributeSpec.js create mode 100644 Specs/Core/GeometryInstanceAttributeSpec.js create mode 100644 Specs/Core/GeometryInstanceSpec.js create mode 100644 Specs/Core/GeometrySpec.js diff --git a/Source/Core/GeometryPipeline.js b/Source/Core/GeometryPipeline.js index a5d8230ed2b6..728e5366f02a 100644 --- a/Source/Core/GeometryPipeline.js +++ b/Source/Core/GeometryPipeline.js @@ -162,7 +162,7 @@ define([ /** * Creates a new {@link Geometry} with LINES representing the provided - * attribute (attributeName) for the provided geometry. This is used + * attribute (attributeName) for the provided geometry. This is used to * visualize vector attributes like normals, binormals, and tangents. * * @param {Geometry} geometry The Geometry instance with the attribute. @@ -176,7 +176,7 @@ define([ * @exception {DeveloperError} geometry.attributes must have an attribute with the same name as the attributeName parameter. * * @example - * var geometry = GeometryPipeline.createLineSegmentsForVectors(geometry2.geometry, 'binormal', 100000.0), + * var geometry = GeometryPipeline.createLineSegmentsForVectors(instance.geometry, 'binormal', 100000.0), */ GeometryPipeline.createLineSegmentsForVectors = function(geometry, attributeName, length) { if (typeof geometry === 'undefined') { @@ -349,9 +349,6 @@ define([ indicesOut[intoIndicesOut] = tempIndex; } else { tempIndex = indicesIn[intoIndicesIn]; - if (tempIndex >= numVertices) { - throw new DeveloperError('Each attribute array in geometry.attributes must have the same number of attributes.'); - } indexCrossReferenceOldToNew[tempIndex] = nextIndex; indicesOut[intoIndicesOut] = nextIndex; @@ -758,7 +755,7 @@ define([ if (modelMatrix.equals(Matrix4.IDENTITY)) { // Already in world coordinates - return; + return instance; } var attributes = instance.geometry.attributes; diff --git a/Specs/Core/GeometryAttributeSpec.js b/Specs/Core/GeometryAttributeSpec.js new file mode 100644 index 000000000000..2a53dbd70ab7 --- /dev/null +++ b/Specs/Core/GeometryAttributeSpec.js @@ -0,0 +1,85 @@ +/*global defineSuite*/ +defineSuite([ + 'Core/GeometryAttribute', + 'Core/ComponentDatatype' + ], function( + GeometryAttribute, + ComponentDatatype) { + "use strict"; + /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/ + + it('constructor', function() { + var color = new GeometryAttribute({ + componentDatatype : ComponentDatatype.UNSIGNED_BYTE, + componentsPerAttribute : 4, + normalize : true, + values : new Uint8Array([ + 255, 0, 0, 255, + 0, 255, 0, 255, + 0, 0, 255, 255 + ]) + }); + + expect(color.componentDatatype).toEqual(ComponentDatatype.UNSIGNED_BYTE); + expect(color.componentsPerAttribute).toEqual(4); + expect(color.normalize).toEqual(true); + expect(color.values).toEqual([ + 255, 0, 0, 255, + 0, 255, 0, 255, + 0, 0, 255, 255 + ]); + }); + + it('clone', function() { + var color = new GeometryAttribute({ + componentDatatype : ComponentDatatype.UNSIGNED_BYTE, + componentsPerAttribute : 4, + normalize : true, + values : new Uint8Array([ + 255, 0, 0, 255, + 0, 255, 0, 255, + 0, 0, 255, 255 + ]) + }); + var clone = color.clone(); + + expect(clone.componentDatatype).toEqual(ComponentDatatype.UNSIGNED_BYTE); + expect(clone.componentsPerAttribute).toEqual(4); + expect(clone.normalize).toEqual(true); + expect(clone.values).not.toBe(color.values); + expect(clone.values instanceof Uint8Array); + expect(clone.values).toEqual([ + 255, 0, 0, 255, + 0, 255, 0, 255, + 0, 0, 255, 255 + ]); + }); + + it('clone with result parameter', function() { + var color = new GeometryAttribute({ + componentDatatype : ComponentDatatype.UNSIGNED_BYTE, + componentsPerAttribute : 4, + normalize : true, + values : new Uint8Array([ + 255, 0, 0, 255, + 0, 255, 0, 255, + 0, 0, 255, 255 + ]) + }); + var result = new GeometryAttribute(); + var clone = color.clone(result); + + expect(clone).toBe(result); + expect(clone.componentDatatype).toEqual(ComponentDatatype.UNSIGNED_BYTE); + expect(clone.componentsPerAttribute).toEqual(4); + expect(clone.normalize).toEqual(true); + expect(clone.values).not.toBe(color.values); + expect(clone.values instanceof Uint8Array); + expect(clone.values).toEqual([ + 255, 0, 0, 255, + 0, 255, 0, 255, + 0, 0, 255, 255 + ]); + }); + +}); diff --git a/Specs/Core/GeometryInstanceAttributeSpec.js b/Specs/Core/GeometryInstanceAttributeSpec.js new file mode 100644 index 000000000000..77a460a86704 --- /dev/null +++ b/Specs/Core/GeometryInstanceAttributeSpec.js @@ -0,0 +1,61 @@ +/*global defineSuite*/ +defineSuite([ + 'Core/GeometryInstanceAttribute', + 'Core/ComponentDatatype' + ], function( + GeometryInstanceAttribute, + ComponentDatatype) { + "use strict"; + /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/ + + it('constructor', function() { + var color = new GeometryInstanceAttribute({ + componentDatatype : ComponentDatatype.UNSIGNED_BYTE, + componentsPerAttribute : 4, + normalize : true, + value : new Uint8Array([255, 255, 0, 255]) + }); + + expect(color.componentDatatype).toEqual(ComponentDatatype.UNSIGNED_BYTE); + expect(color.componentsPerAttribute).toEqual(4); + expect(color.normalize).toEqual(true); + expect(color.value).toEqual([255, 255, 0, 255]); + }); + + it('clone', function() { + var color = new GeometryInstanceAttribute({ + componentDatatype : ComponentDatatype.UNSIGNED_BYTE, + componentsPerAttribute : 4, + normalize : true, + value : new Uint8Array([255, 255, 0, 255]) + }); + var clone = GeometryInstanceAttribute.clone(color); + + expect(clone.componentDatatype).toEqual(ComponentDatatype.UNSIGNED_BYTE); + expect(clone.componentsPerAttribute).toEqual(4); + expect(clone.normalize).toEqual(true); + expect(clone.value).not.toBe(color.value); + expect(clone.value instanceof Uint8Array); + expect(color.value).toEqual([255, 255, 0, 255]); + }); + + it('clone with result parameter', function() { + var color = new GeometryInstanceAttribute({ + componentDatatype : ComponentDatatype.UNSIGNED_BYTE, + componentsPerAttribute : 4, + normalize : true, + value : new Uint8Array([255, 255, 0, 255]) + }); + var result = new GeometryInstanceAttribute(); + var clone = GeometryInstanceAttribute.clone(color, result); + + expect(clone).toBe(result); + expect(clone.componentDatatype).toEqual(ComponentDatatype.UNSIGNED_BYTE); + expect(clone.componentsPerAttribute).toEqual(4); + expect(clone.normalize).toEqual(true); + expect(clone.value).not.toBe(color.value); + expect(clone.value instanceof Uint8Array); + expect(color.value).toEqual([255, 255, 0, 255]); + }); + +}); diff --git a/Specs/Core/GeometryInstanceSpec.js b/Specs/Core/GeometryInstanceSpec.js new file mode 100644 index 000000000000..00a0453a2b91 --- /dev/null +++ b/Specs/Core/GeometryInstanceSpec.js @@ -0,0 +1,159 @@ +/*global defineSuite*/ +defineSuite([ + 'Core/GeometryInstance', + 'Core/Geometry', + 'Core/GeometryAttribute', + 'Core/GeometryInstanceAttribute', + 'Core/ComponentDatatype', + 'Core/BoundingSphere', + 'Core/Cartesian3', + 'Core/PrimitiveType', + 'Core/Matrix4' + ], function( + GeometryInstance, + Geometry, + GeometryAttribute, + GeometryInstanceAttribute, + ComponentDatatype, + BoundingSphere, + Cartesian3, + PrimitiveType, + Matrix4) { + "use strict"; + /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/ + + it('constructor', function() { + var geometry = new Geometry({ + attributes : { + position : new GeometryAttribute({ + componentDatatype : ComponentDatatype.DOUBLE, + componentsPerAttribute : 3, + values : new Float64Array([ + 0.0, 0.0, 0.0, + 1.0, 0.0, 0.0, + 0.0, 1.0, 0.0 + ]) + }) + }, + indices : new Uint16Array([0, 1, 2]), + primitiveType : PrimitiveType.TRIANGLES, + boundingSphere : new BoundingSphere(new Cartesian3(0.5, 0.5, 0.0), 1.0) + }); + var modelMatrix = Matrix4.multiplyByTranslation(Matrix4.IDENTITY, new Cartesian3(0.0, 0.0, 9000000.0)); + var attributes = { + color : new GeometryInstanceAttribute({ + componentDatatype : ComponentDatatype.UNSIGNED_BYTE, + componentsPerAttribute : 4, + normalize : true, + value : new Uint8Array([255, 255, 0, 255]) + }) + }; + var instance = new GeometryInstance({ + geometry : geometry, + modelMatrix : modelMatrix, + id : 'geometry', + attributes : attributes + }); + + expect(instance.geometry).toBe(geometry); + expect(instance.modelMatrix).toEqual(modelMatrix); + expect(instance.id).toEqual('geometry'); + expect(attributes).toBe(attributes); + }); + + it('clone', function() { + var geometry = new Geometry({ + attributes : { + position : new GeometryAttribute({ + componentDatatype : ComponentDatatype.DOUBLE, + componentsPerAttribute : 3, + values : new Float64Array([ + 0.0, 0.0, 0.0, + 1.0, 0.0, 0.0, + 0.0, 1.0, 0.0 + ]) + }) + }, + indices : new Uint16Array([0, 1, 2]), + primitiveType : PrimitiveType.TRIANGLES, + boundingSphere : new BoundingSphere(new Cartesian3(0.5, 0.5, 0.0), 1.0) + }); + var modelMatrix = Matrix4.multiplyByTranslation(Matrix4.IDENTITY, new Cartesian3(0.0, 0.0, 9000000.0)); + var attributes = { + color : new GeometryInstanceAttribute({ + componentDatatype : ComponentDatatype.UNSIGNED_BYTE, + componentsPerAttribute : 4, + normalize : true, + value : new Uint8Array([255, 255, 0, 255]) + }) + }; + var instance = new GeometryInstance({ + geometry : geometry, + modelMatrix : modelMatrix, + id : 'geometry', + attributes : attributes + }); + var clone = instance.clone(); + + expect(clone.geometry).toBeDefined(); + expect(clone.geometry.attributes).toBeDefined(); + expect(clone.geometry.attributes.position).toBeDefined(); + expect(clone.geometry.indices).toBeDefined(); + + expect(clone.modelMatrix).toEqual(instance.modelMatrix); + expect(clone.id).toEqual(instance.id); + + expect(clone.attributes).toBeDefined(); + expect(clone.attributes.color).toBeDefined(); + }); + + it('clone with result parameter', function() { + var geometry = new Geometry({ + attributes : { + position : new GeometryAttribute({ + componentDatatype : ComponentDatatype.DOUBLE, + componentsPerAttribute : 3, + values : new Float64Array([ + 0.0, 0.0, 0.0, + 1.0, 0.0, 0.0, + 0.0, 1.0, 0.0 + ]) + }) + }, + indices : new Uint16Array([0, 1, 2]), + primitiveType : PrimitiveType.TRIANGLES, + boundingSphere : new BoundingSphere(new Cartesian3(0.5, 0.5, 0.0), 1.0) + }); + var modelMatrix = Matrix4.multiplyByTranslation(Matrix4.IDENTITY, new Cartesian3(0.0, 0.0, 9000000.0)); + var attributes = { + color : new GeometryInstanceAttribute({ + componentDatatype : ComponentDatatype.UNSIGNED_BYTE, + componentsPerAttribute : 4, + normalize : true, + value : new Uint8Array([255, 255, 0, 255]) + }) + }; + var instance = new GeometryInstance({ + geometry : geometry, + modelMatrix : modelMatrix, + id : 'geometry', + attributes : attributes + }); + var result = new GeometryInstance(); + var clone = instance.clone(result); + + expect(clone).toBe(result); + + expect(clone.geometry).toBeDefined(); + expect(clone.geometry.attributes).toBeDefined(); + expect(clone.geometry.attributes.position).toBeDefined(); + expect(clone.geometry.indices).toBeDefined(); + + expect(clone.modelMatrix).toEqual(instance.modelMatrix); + expect(clone.id).toEqual(instance.id); + + expect(clone.attributes).toBeDefined(); + expect(clone.attributes.color).toBeDefined(); + }); + +}); diff --git a/Specs/Core/GeometryPipelineSpec.js b/Specs/Core/GeometryPipelineSpec.js index 916ab0f2bd38..52b095cb1f59 100644 --- a/Specs/Core/GeometryPipelineSpec.js +++ b/Specs/Core/GeometryPipelineSpec.js @@ -14,7 +14,8 @@ defineSuite([ 'Core/GeometryAttribute', 'Core/GeometryInstance', 'Core/VertexFormat', - 'Core/Math' + 'Core/Math', + 'Core/BoundingSphere' ], function( GeometryPipeline, PrimitiveType, @@ -30,7 +31,8 @@ defineSuite([ GeometryAttribute, GeometryInstance, VertexFormat, - CesiumMath) { + CesiumMath, + BoundingSphere) { "use strict"; /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/ @@ -118,6 +120,63 @@ defineSuite([ }).toThrow(); }); + it('createLineSegmentsForVectors', function() { + var geometry = new Geometry({ + attributes : { + position : new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : [0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0] + }), + normal : new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : [0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0] + }) + }, + primitiveType : PrimitiveType.TRIANGLES, + boundingSphere : new BoundingSphere(new Cartesian3(0.5, 0.5, 0.0), 1.0) + }); + var lines = GeometryPipeline.createLineSegmentsForVectors(geometry, 'normal', 1.0); + var linePositions = [0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0]; + + expect(lines.attributes).toBeDefined(); + expect(lines.attributes.position).toBeDefined(); + expect(lines.attributes.position.values).toEqual(linePositions); + expect(lines.primitiveType).toEqual(PrimitiveType.LINES); + expect(lines.boundingSphere.center).toEqual(geometry.boundingSphere.center); + expect(lines.boundingSphere.radius).toEqual(geometry.boundingSphere.radius + 1.0); + }); + + it('createLineSegmentsForVectors throws without geometry', function() { + expect(function() { + GeometryPipeline.createLineSegmentsForVectors(); + }).toThrow(); + }); + + it('createLineSegmentsForVectors throws without geometry.attributes.position', function() { + expect(function() { + GeometryPipeline.createLineSegmentsForVectors(); + }).toThrow(); + }); + + it('createLineSegmentsForVectors throws when geometry.attributes does not vae an attributeName property', function() { + var geometry = new Geometry({ + attributes : { + position : new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : [0.0, 1.0, 2.0, 3.0, 4.0, 5.0] + }) + }, + primitiveType : PrimitiveType.TRIANGLES + }); + + expect(function() { + GeometryPipeline.createLineSegmentsForVectors(geometry, 'binormal'); + }).toThrow(); + }); + it('creates attribute indices', function() { var geometry = new Geometry({ attributes : { @@ -558,6 +617,95 @@ defineSuite([ }).toThrow(); }); + it('transformToWorldCoordinates', function() { + var instance = new GeometryInstance({ + geometry : new Geometry({ + attributes : { + position : new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : [ + 0.0, 0.0, 0.0, + 1.0, 0.0, 0.0, + 0.0, 1.0, 0.0 + ] + }), + normal : new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : [ + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0 + ] + }) + }, + indices : [0, 1, 2], + primitiveType : PrimitiveType.TRIANGLES, + boundingSphere : new BoundingSphere(new Cartesian3(0.5, 0.5, 0.0), 1.0) + }), + modelMatrix : new Matrix4(0.0, 0.0, 1.0, 0.0, + 1.0, 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 1.0) + }); + + var transformed = GeometryPipeline.transformToWorldCoordinates(instance); + var transformedPositions = [0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0]; + var transformedNormals = [1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0]; + + expect(transformed.geometry.attributes.position.values).toEqual(transformedPositions); + expect(transformed.geometry.attributes.normal.values).toEqual(transformedNormals); + expect(transformed.geometry.boundingSphere).toEqual(new BoundingSphere(new Cartesian3(0.0, 0.5, 0.5), 1.0)); + expect(transformed.modelMatrix).toEqual(Matrix4.IDENTITY); + }); + + it('transformToWorldCoordinates does nothing when already in world coordinates', function() { + var instance = new GeometryInstance({ + geometry : new Geometry({ + attributes : { + position : new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : [ + 0.0, 0.0, 0.0, + 1.0, 0.0, 0.0, + 0.0, 1.0, 0.0 + ] + }), + normal : new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : [ + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0 + ] + }) + }, + indices : [0, 1, 2], + primitiveType : PrimitiveType.TRIANGLES, + boundingSphere : new BoundingSphere(new Cartesian3(0.5, 0.5, 0.0), 1.0) + }), + modelMatrix : Matrix4.IDENTITY + }); + + var transformed = GeometryPipeline.transformToWorldCoordinates(instance); + var transformedPositions = [0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0]; + var transformedNormals = [0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0]; + + expect(transformed.geometry.attributes.position.values).toEqual(transformedPositions); + expect(transformed.geometry.attributes.normal.values).toEqual(transformedNormals); + expect(transformed.geometry.boundingSphere).toEqual(new BoundingSphere(new Cartesian3(0.5, 0.5, 0.0), 1.0)); + expect(transformed.modelMatrix).toEqual(Matrix4.IDENTITY); + }); + + it('transformToWorldCoordinates throws without an instance', function() { + expect(function() { + GeometryPipeline.transformToWorldCoordinates(); + }).toThrow(); + }); + it('combine combines one geometry', function() { var instance = new GeometryInstance({ geometry : new Geometry({ @@ -680,7 +828,50 @@ defineSuite([ })); }); - it('combine throws with instances', function() { + it('combine combines bounding spheres', function() { + var instance = new GeometryInstance({ + geometry : new Geometry({ + attributes : { + position : new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : [ + 0.0, 0.0, 0.0, + 1.0, 0.0, 0.0, + 0.0, 1.0, 0.0 + ] + }) + }, + indices : [0, 1, 2], + primitiveType : PrimitiveType.TRIANGLES, + boundingSphere : new BoundingSphere(new Cartesian3(0.5, 0.5, 0.0), 1.0) + }) + }); + var anotherInstance = new GeometryInstance({ + geometry : new Geometry({ + attributes : { + position : new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : [ + 1.0, 0.0, 0.0, + 2.0, 0.0, 0.0, + 1.0, 1.0, 0.0 + ] + }) + }, + indices : [0, 1, 2], + primitiveType : PrimitiveType.TRIANGLES, + boundingSphere : new BoundingSphere(new Cartesian3(1.5, 0.5, 0.0), 1.0) + }) + }); + + var combined = GeometryPipeline.combine([instance, anotherInstance]); + var expected = BoundingSphere.union(instance.geometry.boundingSphere, anotherInstance.geometry.boundingSphere); + expect(combined.boundingSphere).toEqual(expected); + }); + + it('combine throws without instances', function() { expect(function() { GeometryPipeline.combine(); }).toThrow(); @@ -703,7 +894,7 @@ defineSuite([ } }) }), - modelMatrix : Matrix4.fromScale(1.0) + modelMatrix : Matrix4.fromScale(new Cartesian3(1.0, 1.0, 1.0)) }); var instance1 = new GeometryInstance({ @@ -716,7 +907,7 @@ defineSuite([ } }) }), - modelMatrix : Matrix4.fromScale(2.0) + modelMatrix : Matrix4.fromScale(new Cartesian3(2.0, 2.0, 2.0)) }); expect(function() { @@ -755,6 +946,38 @@ defineSuite([ }).toThrow(); }); + it('combine throws when instance geometries do not all have the same primitive type', function() { + var instance0 = new GeometryInstance({ + geometry : new Geometry({ + attributes : new GeometryAttribute({ + position : { + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : [0.0, 0.0, 0.0] + } + }), + primitiveType : PrimitiveType.POINTS + }) + }); + + var instance1 = new GeometryInstance({ + geometry : new Geometry({ + attributes : new GeometryAttribute({ + position : { + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : [0.0, 0.0, 0.0, 1.0, 0.0, 0.0] + } + }), + primitiveType : PrimitiveType.LINES + }) + }); + + expect(function() { + GeometryPipeline.combine([instance0, instance1]); + }).toThrow(); + }); + it('computeNormal throws when geometry is undefined', function() { expect(function() { GeometryPipeline.computeNormal(); diff --git a/Specs/Core/GeometrySpec.js b/Specs/Core/GeometrySpec.js new file mode 100644 index 000000000000..194dbb3e0492 --- /dev/null +++ b/Specs/Core/GeometrySpec.js @@ -0,0 +1,257 @@ +/*global defineSuite*/ +defineSuite([ + 'Core/Geometry', + 'Core/GeometryAttribute', + 'Core/ComponentDatatype', + 'Core/BoundingSphere', + 'Core/Cartesian3', + 'Core/PrimitiveType' + ], function( + Geometry, + GeometryAttribute, + ComponentDatatype, + BoundingSphere, + Cartesian3, + PrimitiveType) { + "use strict"; + /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/ + + it('constructor', function() { + var attributes = { + position : new GeometryAttribute({ + componentDatatype : ComponentDatatype.DOUBLE, + componentsPerAttribute : 3, + values : new Float64Array([ + 0.0, 0.0, 0.0, + 1.0, 0.0, 0.0, + 0.0, 1.0, 0.0 + ]) + }) + }; + var indices = new Uint16Array([0, 1, 2]); + var boundingSphere = new BoundingSphere(new Cartesian3(0.5, 0.5, 0.0), 1.0); + + var geometry = new Geometry({ + attributes : attributes, + indices : indices, + primitiveType : PrimitiveType.TRIANGLES, + boundingSphere : boundingSphere + }); + + expect(geometry.attributes).toBe(attributes); + expect(geometry.indices).toBe(indices); + expect(geometry.primitiveType).toEqual(PrimitiveType.TRIANGLES); + expect(geometry.boundingSphere).toBe(boundingSphere); + }); + + it('clone returns undefined when geometry is undefined', function() { + expect(Geometry.clone()).not.toBeDefined(); + }); + + it('clone', function() { + var attributes = { + position : new GeometryAttribute({ + componentDatatype : ComponentDatatype.DOUBLE, + componentsPerAttribute : 3, + values : new Float64Array([ + 0.0, 0.0, 0.0, + 1.0, 0.0, 0.0, + 0.0, 1.0, 0.0 + ]) + }), + st : new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 2, + values : new Float32Array([ + 0.0, 0.0, + 1.0, 0.0, + 0.0, 1.0 + ]) + }) + }; + var indices = new Uint16Array([0, 1, 2]); + var boundingSphere = new BoundingSphere(new Cartesian3(0.5, 0.5, 0.0), 1.0); + + var geometry = new Geometry({ + attributes : attributes, + indices : indices, + primitiveType : PrimitiveType.TRIANGLES, + boundingSphere : boundingSphere + }); + var clone = Geometry.clone(geometry); + + expect(clone.attributes).not.toBe(geometry.attributes); + expect(clone.attributes.position).toBeDefined(); + expect(clone.attributes.st).toBeDefined(); + + expect(clone.indices).toBeDefined(); + expect(clone.indices).not.toBe(geometry.indices); + expect(clone.indices instanceof Uint16Array).toEqual(true); + + expect(clone.primitiveType).toEqual(geometry.primitiveType); + expect(clone.boundingSphere).toEqual(geometry.boundingSphere); + }); + + it('clone with undefined indices', function() { + var attributes = { + position : new GeometryAttribute({ + componentDatatype : ComponentDatatype.DOUBLE, + componentsPerAttribute : 3, + values : new Float64Array([ + 0.0, 0.0, 0.0, + 1.0, 0.0, 0.0, + 0.0, 1.0, 0.0 + ]) + }), + st : new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 2, + values : new Float32Array([ + 0.0, 0.0, + 1.0, 0.0, + 0.0, 1.0 + ]) + }) + }; + var boundingSphere = new BoundingSphere(new Cartesian3(0.5, 0.5, 0.0), 1.0); + + var geometry = new Geometry({ + attributes : attributes, + primitiveType : PrimitiveType.TRIANGLES, + boundingSphere : boundingSphere + }); + var clone = Geometry.clone(geometry); + + expect(clone.attributes).not.toBe(geometry.attributes); + expect(clone.attributes.position).toBeDefined(); + expect(clone.attributes.st).toBeDefined(); + + expect(clone.indices).not.toBeDefined(); + + expect(clone.primitiveType).toEqual(geometry.primitiveType); + expect(clone.boundingSphere).toEqual(geometry.boundingSphere); + }); + + it('clone with result parameter', function() { + var attributes = { + position : new GeometryAttribute({ + componentDatatype : ComponentDatatype.DOUBLE, + componentsPerAttribute : 3, + values : new Float64Array([ + 0.0, 0.0, 0.0, + 1.0, 0.0, 0.0, + 0.0, 1.0, 0.0 + ]) + }), + st : new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 2, + values : new Float32Array([ + 0.0, 0.0, + 1.0, 0.0, + 0.0, 1.0 + ]) + }) + }; + var indices = new Uint16Array([0, 1, 2]); + var boundingSphere = new BoundingSphere(new Cartesian3(0.5, 0.5, 0.0), 1.0); + + var geometry = new Geometry({ + attributes : attributes, + indices : indices, + primitiveType : PrimitiveType.TRIANGLES, + boundingSphere : boundingSphere + }); + var result = new Geometry(); + var clone = Geometry.clone(geometry, result); + + expect(clone).toBe(result); + + expect(clone.attributes).not.toBe(geometry.attributes); + expect(clone.attributes.position).toBeDefined(); + expect(clone.attributes.st).toBeDefined(); + + expect(clone.indices).toBeDefined(); + expect(clone.indices).not.toBe(geometry.indices); + expect(clone.indices instanceof Uint16Array).toEqual(true); + + expect(clone.primitiveType).toEqual(geometry.primitiveType); + expect(clone.boundingSphere).toEqual(geometry.boundingSphere); + }); + + it('computeNumberOfVertices', function() { + var attributes = { + position : new GeometryAttribute({ + componentDatatype : ComponentDatatype.DOUBLE, + componentsPerAttribute : 3, + values : new Float64Array([ + 0.0, 0.0, 0.0, + 1.0, 0.0, 0.0, + 0.0, 1.0, 0.0 + ]) + }), + st : new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 2, + values : new Float32Array([ + 0.0, 0.0, + 1.0, 0.0, + 0.0, 1.0 + ]) + }) + }; + var indices = new Uint16Array([0, 1, 2]); + var boundingSphere = new BoundingSphere(new Cartesian3(0.5, 0.5, 0.0), 1.0); + + var geometry = new Geometry({ + attributes : attributes, + indices : indices, + primitiveType : PrimitiveType.TRIANGLES, + boundingSphere : boundingSphere + }); + + expect(Geometry.computeNumberOfVertices(geometry)).toEqual(3); + }); + + it('computeNumberOfVertices throws when attributes have different number of vertices', function() { + var attributes = { + position : new GeometryAttribute({ + componentDatatype : ComponentDatatype.DOUBLE, + componentsPerAttribute : 3, + values : new Float64Array([ + 0.0, 0.0, 0.0, + 1.0, 0.0, 0.0, + 0.0, 1.0, 0.0 + ]) + }), + st : new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 2, + values : new Float32Array([ + 0.0, 0.0, + 1.0, 0.0 + ]) + }) + }; + var indices = new Uint16Array([0, 1, 2]); + var boundingSphere = new BoundingSphere(new Cartesian3(0.5, 0.5, 0.0), 1.0); + + var geometry = new Geometry({ + attributes : attributes, + indices : indices, + primitiveType : PrimitiveType.TRIANGLES, + boundingSphere : boundingSphere + }); + + expect(function() { + Geometry.computeNumberOfVertices(geometry); + }).toThrow(); + }); + + it('computeNumberOfVertices throws without geometry', function() { + expect(function() { + Geometry.computeNumberOfVertices(); + }).toThrow(); + }); + +}); From 9b732f190004b6277740e0a1e029b195498299f5 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 1 Jul 2013 20:39:11 -0400 Subject: [PATCH 284/306] Add more tests. --- Source/Core/PolygonGeometry.js | 4 - Source/Scene/DebugAppearance.js | 32 +-- Source/Scene/Projections.js | 108 --------- Specs/Core/BoxGeometrySpec.js | 6 +- .../Core/ShowGeometryInstanceAttributeSpec.js | 30 +++ Specs/Core/SimplePolylineGeometrySpec.js | 40 ++++ Specs/Scene/AppearanceSpec.js | 91 +++++++ Specs/Scene/DebugAppearanceSpec.js | 119 +++++++++ Specs/Scene/EllipsoidSurfaceAppearanceSpec.js | 28 +++ Specs/Scene/ExtentPrimitiveSpec.js | 226 ++++++++++++++++++ Specs/Scene/PolygonSpec.js | 8 - 11 files changed, 552 insertions(+), 140 deletions(-) delete mode 100644 Source/Scene/Projections.js create mode 100644 Specs/Core/ShowGeometryInstanceAttributeSpec.js create mode 100644 Specs/Core/SimplePolylineGeometrySpec.js create mode 100644 Specs/Scene/AppearanceSpec.js create mode 100644 Specs/Scene/DebugAppearanceSpec.js create mode 100644 Specs/Scene/EllipsoidSurfaceAppearanceSpec.js create mode 100644 Specs/Scene/ExtentPrimitiveSpec.js diff --git a/Source/Core/PolygonGeometry.js b/Source/Core/PolygonGeometry.js index 5cfef42c9a8c..7111becf2571 100644 --- a/Source/Core/PolygonGeometry.js +++ b/Source/Core/PolygonGeometry.js @@ -76,10 +76,6 @@ define([ } } - if (typeof result === 'undefined') { - result = new BoundingRectangle(); - } - result.x = minX; result.y = minY; result.width = maxX - minX; diff --git a/Source/Scene/DebugAppearance.js b/Source/Scene/DebugAppearance.js index 619b316e3b08..e7174f5c363d 100644 --- a/Source/Scene/DebugAppearance.js +++ b/Source/Scene/DebugAppearance.js @@ -57,23 +57,23 @@ define([ // All other attributes, both well-known and custom if (attributeName === 'st') { glslDatatype = 'vec2'; + } - switch(glslDatatype) { - case 'float': - getColor = 'vec4 getColor() { return vec4(vec3(' + varyingName + '), 1.0); }\n'; - break; - case 'vec2': - getColor = 'vec4 getColor() { return vec4(' + varyingName + ', 0.0, 1.0); }\n'; - break; - case 'vec3': - getColor = 'vec4 getColor() { return vec4(' + varyingName + ', 1.0); }\n'; - break; - case 'vec4': - getColor = 'vec4 getColor() { return ' + varyingName + '; }\n'; - break; - default: - throw new DeveloperError('options.glslDatatype must be float, vec2, vec3, or vec4.'); - } + switch(glslDatatype) { + case 'float': + getColor = 'vec4 getColor() { return vec4(vec3(' + varyingName + '), 1.0); }\n'; + break; + case 'vec2': + getColor = 'vec4 getColor() { return vec4(' + varyingName + ', 0.0, 1.0); }\n'; + break; + case 'vec3': + getColor = 'vec4 getColor() { return vec4(' + varyingName + ', 1.0); }\n'; + break; + case 'vec4': + getColor = 'vec4 getColor() { return ' + varyingName + '; }\n'; + break; + default: + throw new DeveloperError('options.glslDatatype must be float, vec2, vec3, or vec4.'); } } diff --git a/Source/Scene/Projections.js b/Source/Scene/Projections.js deleted file mode 100644 index a92c288888b3..000000000000 --- a/Source/Scene/Projections.js +++ /dev/null @@ -1,108 +0,0 @@ -/*global define*/ -define([ - '../Core/DeveloperError', - '../Core/Enumeration' - ], function( - DeveloperError, - Enumeration) { - "use strict"; - - /** - * DOC_TBA - * - * @exports Projections - */ - var Projections = { - /** - * DOC_TBA - * - * @type {Enumeration} - * @constant - * @default 0 - */ - WGS84 : new Enumeration(0, 'WGS84', { - toWgs84 : function(extent, image) { - return image; - } - }), - - /** - * DOC_TBA - * - * @type {Enumeration} - * @constant - * @default 1 - */ - MERCATOR : new Enumeration(1, 'MERCATOR', { - toWgs84 : function(extent, image) { - if (typeof extent === 'undefined' || typeof extent.north === 'undefined' || typeof extent.south === 'undefined') { - throw new DeveloperError('extent, extent.north and extent.south are required.'); - } - - if (typeof image === 'undefined') { - throw new DeveloperError('image is required.'); - } - - var width = parseInt(image.width, 10); - var height = parseInt(image.height, 10); - var wRowBytes = width * 4; // Always 4 bytes per pixel. - - // draw image to canvas and get the pixels - var canvas = document.createElement('canvas'); - canvas.width = width; - canvas.height = height; - var context = canvas.getContext('2d'); - context.drawImage(image, 0, 0); - var fromPixels = context.getImageData(0, 0, width, height).data; - - // create array of pixels - var newImageData = context.createImageData(width, height); - var toPixels = newImageData.data; - - // WGS84 parameters - var deltaWLat = (extent.north - extent.south) / height; - var currentWLat = extent.north - (0.5 * deltaWLat); - - // mercator parameters - var sinTheta = Math.sin(extent.south); - var minMLat = 0.5 * Math.log((1 + sinTheta) / (1 - sinTheta)); - sinTheta = Math.sin(extent.north); - var maxMLat = 0.5 * Math.log((1 + sinTheta) / (1 - sinTheta)); - var invMLatDim = 1.0 / (maxMLat - minMLat); - - // first row - var heightMinusOne = height - 1; - var i = 0; - for (; i < wRowBytes; ++i) { - toPixels[i] = fromPixels[i]; - } - - // interior rows - var end, mLat, mRow; - var j = 1; - for (; j < heightMinusOne; ++j, currentWLat -= deltaWLat) { - sinTheta = Math.sin(currentWLat); - mLat = 0.5 * Math.log((1.0 + sinTheta) / (1.0 - sinTheta)); - mRow = Math.floor(heightMinusOne - ((heightMinusOne * (mLat - minMLat) * invMLatDim))); - end = i + wRowBytes; - for ( var k = 0; i < end; ++i, ++k) { - toPixels[i] = fromPixels[mRow * wRowBytes + k]; - } - } - - // last row - end = i + wRowBytes; - for (j = 0; i < end; ++i, ++j) { - toPixels[i] = fromPixels[i]; - } - - // paint new image to canvas - context.putImageData(newImageData, 0, 0); - - return canvas; - } - }) - }; - - return Projections; -}); diff --git a/Specs/Core/BoxGeometrySpec.js b/Specs/Core/BoxGeometrySpec.js index 962300714853..33df211eb5e0 100644 --- a/Specs/Core/BoxGeometrySpec.js +++ b/Specs/Core/BoxGeometrySpec.js @@ -2,13 +2,11 @@ defineSuite([ 'Core/BoxGeometry', 'Core/VertexFormat', - 'Core/Cartesian3', - 'Core/Matrix4' + 'Core/Cartesian3' ], function( BoxGeometry, VertexFormat, - Cartesian3, - Matrix4) { + Cartesian3) { "use strict"; /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/ diff --git a/Specs/Core/ShowGeometryInstanceAttributeSpec.js b/Specs/Core/ShowGeometryInstanceAttributeSpec.js new file mode 100644 index 000000000000..89f9e813a19a --- /dev/null +++ b/Specs/Core/ShowGeometryInstanceAttributeSpec.js @@ -0,0 +1,30 @@ +/*global defineSuite*/ +defineSuite([ + 'Core/ShowGeometryInstanceAttribute', + 'Core/ComponentDatatype' + ], function( + ShowGeometryInstanceAttribute, + ComponentDatatype) { + "use strict"; + /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/ + + it('constructor', function() { + var attribute = new ShowGeometryInstanceAttribute(false); + expect(attribute.componentDatatype).toEqual(ComponentDatatype.UNSIGNED_BYTE); + expect(attribute.componentsPerAttribute).toEqual(1); + expect(attribute.normalize).toEqual(true); + + expect(attribute.value).toEqual(new Uint8Array([false])); + }); + + it('toValue', function() { + expect(ShowGeometryInstanceAttribute.toValue(true)).toEqual(new Uint8Array([true])); + }); + + it('toValue throws without a color', function() { + expect(function() { + ShowGeometryInstanceAttribute.toValue(); + }).toThrow(); + }); + +}); diff --git a/Specs/Core/SimplePolylineGeometrySpec.js b/Specs/Core/SimplePolylineGeometrySpec.js new file mode 100644 index 000000000000..a59d84d8a423 --- /dev/null +++ b/Specs/Core/SimplePolylineGeometrySpec.js @@ -0,0 +1,40 @@ +/*global defineSuite*/ +defineSuite([ + 'Core/SimplePolylineGeometry', + 'Core/Cartesian3', + 'Core/BoundingSphere', + 'Core/PrimitiveType' + ], function( + SimplePolylineGeometry, + Cartesian3, + BoundingSphere, + PrimitiveType) { + "use strict"; + /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/ + + it('constructor throws with no positions', function() { + expect(function() { + return new SimplePolylineGeometry(); + }).toThrow(); + }); + + it('constructor throws with less than two positions', function() { + expect(function() { + return new SimplePolylineGeometry({ + positions : [Cartesian3.ZERO] + }); + }).toThrow(); + }); + + it('constructor computes all vertex attributes', function() { + var positions = [new Cartesian3(), new Cartesian3(1.0, 0.0, 0.0), new Cartesian3(2.0, 0.0, 0.0)]; + var line = new SimplePolylineGeometry({ + positions : positions + }); + + expect(line.attributes.position.values).toEqual([0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 2.0, 0.0, 0.0]); + expect(line.indices).toEqual([0, 1, 1, 2]); + expect(line.primitiveType).toEqual(PrimitiveType.LINES); + expect(line.boundingSphere).toEqual(BoundingSphere.fromPoints(positions)); + }); +}); \ No newline at end of file diff --git a/Specs/Scene/AppearanceSpec.js b/Specs/Scene/AppearanceSpec.js new file mode 100644 index 000000000000..0e696bedee6e --- /dev/null +++ b/Specs/Scene/AppearanceSpec.js @@ -0,0 +1,91 @@ +/*global defineSuite*/ +defineSuite([ + 'Scene/Appearance', + 'Scene/Material', + 'Renderer/BlendingState', + 'Renderer/CullFace' + ], function( + Appearance, + Material, + BlendingState, + CullFace) { + "use strict"; + /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/ + + it('constructor', function() { + var material = Material.fromType(undefined, 'Color'); + var vs = + 'attribute vec3 position3DHigh;\n' + + 'attribute vec3 position3DLow;\n' + + 'attribute vec4 color;\n' + + 'varying vec4 v_color;\n' + + 'void main() {\n' + + ' gl_Position = czm_modelViewProjectionRelativeToEye * czm_computePosition();\n' + + ' v_color = color;\n' + + '}\n'; + var fs = + 'varying vec4 v_color;\n' + + 'void main() {\n' + + ' gl_FragColor = v_color;\n' + + '}\n'; + var renderState = { + depthTest : { + enabled : true + } + }; + var appearance = new Appearance({ + material : material, + vertexShaderSource : vs, + fragmentShaderSource : fs, + renderState : renderState + }); + + expect(appearance.material).toBe(material); + expect(appearance.vertexShaderSource).toBe(vs); + expect(appearance.fragmentShaderSource).toBe(fs); + expect(appearance.renderState).toBe(renderState); + }); + + it('getFragmentShaderSource', function() { + var fs = + 'varying vec4 v_color;\n' + + 'void main() {\n' + + ' gl_FragColor = v_color;\n' + + '}\n'; + var appearance = new Appearance({ + fragmentShaderSource : fs + }); + + expect(appearance.getFragmentShaderSource().indexOf(fs)).toBeGreaterThan(-1); + }); + + it('getFragmentShaderSource with material', function() { + var material = Material.fromType(undefined, 'Color'); + var fs = + 'varying vec4 v_color;\n' + + 'void main() {\n' + + ' gl_FragColor = v_color;\n' + + '}\n'; + var appearance = new Appearance({ + material : material, + fragmentShaderSource : fs + }); + + var fragmentSource = appearance.getFragmentShaderSource(); + expect(fragmentSource.indexOf(material.shaderSource)).toBeGreaterThan(-1); + expect(fragmentSource.indexOf(fs)).toBeGreaterThan(-1); + }); + + it('getDefaultRenderState', function() { + var renderState = Appearance.getDefaultRenderState(true, true); + + expect(renderState.depthTest).toBeDefined(); + expect(renderState.depthTest.enabled).toEqual(true); + expect(renderState.depthMask).toEqual(false); + expect(renderState.blending).toEqual(BlendingState.ALPHA_BLEND); + expect(renderState.cull).toBeDefined(); + expect(renderState.cull.enabled).toEqual(true); + expect(renderState.cull.face).toEqual(CullFace.BACK); + }); + +}); diff --git a/Specs/Scene/DebugAppearanceSpec.js b/Specs/Scene/DebugAppearanceSpec.js new file mode 100644 index 000000000000..140feae65580 --- /dev/null +++ b/Specs/Scene/DebugAppearanceSpec.js @@ -0,0 +1,119 @@ +/*global defineSuite*/ +defineSuite([ + 'Scene/DebugAppearance', + 'Scene/Appearance' + ], function( + DebugAppearance, + Appearance) { + "use strict"; + /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/ + + it('constructor throws without attributeName', function() { + expect(function() { + return new DebugAppearance(); + }).toThrow(); + }); + + it('default construct with normal, binormal, or tangent attribute name', function() { + var a = new DebugAppearance({ + attributeName : 'normal' + }); + + expect(a.vertexShaderSource).toBeDefined(); + expect(a.vertexShaderSource.indexOf('normal')).toBeGreaterThan(-1); + expect(a.vertexShaderSource.indexOf('v_normal')).toBeGreaterThan(-1); + + expect(a.fragmentShaderSource).toBeDefined(); + expect(a.fragmentShaderSource.indexOf('v_normal')).toBeGreaterThan(-1); + + expect(a.material).not.toBeDefined(); + expect(a.attributeName).toEqual('normal'); + expect(a.glslDatatype).toEqual('vec3'); + expect(a.renderState).toEqual(Appearance.getDefaultRenderState(false, false)); + }); + + it('default construct with st attribute name', function() { + var a = new DebugAppearance({ + attributeName : 'st' + }); + + expect(a.vertexShaderSource).toBeDefined(); + expect(a.vertexShaderSource.indexOf('st')).toBeGreaterThan(-1); + expect(a.vertexShaderSource.indexOf('v_st')).toBeGreaterThan(-1); + + expect(a.fragmentShaderSource).toBeDefined(); + expect(a.fragmentShaderSource.indexOf('v_st')).toBeGreaterThan(-1); + + expect(a.material).not.toBeDefined(); + expect(a.attributeName).toEqual('st'); + expect(a.glslDatatype).toEqual('vec2'); + expect(a.renderState).toEqual(Appearance.getDefaultRenderState(false, false)); + }); + + it('debug appearance with float attribute name', function() { + var a = new DebugAppearance({ + attributeName : 'rotation', + glslDatatype : 'float' + }); + + expect(a.vertexShaderSource).toBeDefined(); + expect(a.vertexShaderSource.indexOf('rotation')).toBeGreaterThan(-1); + expect(a.vertexShaderSource.indexOf('v_rotation')).toBeGreaterThan(-1); + + expect(a.fragmentShaderSource).toBeDefined(); + expect(a.fragmentShaderSource.indexOf('v_rotation')).toBeGreaterThan(-1); + + expect(a.material).not.toBeDefined(); + expect(a.attributeName).toEqual('rotation'); + expect(a.glslDatatype).toEqual('float'); + expect(a.renderState).toEqual(Appearance.getDefaultRenderState(false, false)); + }); + + it('debug appearance with vec3 attribute name', function() { + var a = new DebugAppearance({ + attributeName : 'str', + glslDatatype : 'vec3' + }); + + expect(a.vertexShaderSource).toBeDefined(); + expect(a.vertexShaderSource.indexOf('str')).toBeGreaterThan(-1); + expect(a.vertexShaderSource.indexOf('v_str')).toBeGreaterThan(-1); + + expect(a.fragmentShaderSource).toBeDefined(); + expect(a.fragmentShaderSource.indexOf('v_str')).toBeGreaterThan(-1); + + expect(a.material).not.toBeDefined(); + expect(a.attributeName).toEqual('str'); + expect(a.glslDatatype).toEqual('vec3'); + expect(a.renderState).toEqual(Appearance.getDefaultRenderState(false, false)); + }); + + it('debug appearance with vec4 attribute name', function() { + var a = new DebugAppearance({ + attributeName : 'quaternion', + glslDatatype : 'vec4' + }); + + expect(a.vertexShaderSource).toBeDefined(); + expect(a.vertexShaderSource.indexOf('quaternion')).toBeGreaterThan(-1); + expect(a.vertexShaderSource.indexOf('v_quaternion')).toBeGreaterThan(-1); + + expect(a.fragmentShaderSource).toBeDefined(); + expect(a.fragmentShaderSource.indexOf('v_quaternion')).toBeGreaterThan(-1); + + expect(a.material).not.toBeDefined(); + expect(a.attributeName).toEqual('quaternion'); + expect(a.glslDatatype).toEqual('vec4'); + expect(a.renderState).toEqual(Appearance.getDefaultRenderState(false, false)); + }); + + it('debug appearance throws with invalid glsl datatype', function() { + expect(function() { + return new DebugAppearance({ + attributeName : 'invalid_datatype', + glslDatatype : 'invalid' + }); + }).toThrow(); + }); + +}); diff --git a/Specs/Scene/EllipsoidSurfaceAppearanceSpec.js b/Specs/Scene/EllipsoidSurfaceAppearanceSpec.js new file mode 100644 index 000000000000..b3c9c3acd596 --- /dev/null +++ b/Specs/Scene/EllipsoidSurfaceAppearanceSpec.js @@ -0,0 +1,28 @@ +/*global defineSuite*/ +defineSuite([ + 'Scene/EllipsoidSurfaceAppearance', + 'Scene/Appearance', + 'Scene/Material' + ], function( + EllipsoidSurfaceAppearance, + Appearance, + Material) { + "use strict"; + /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/ + + it('constructor', function() { + var a = new EllipsoidSurfaceAppearance(); + + expect(a.material).toBeDefined(); + expect(a.material.type).toEqual(Material.ColorType); + expect(a.vertexShaderSource).toBeDefined(); + expect(a.fragmentShaderSource).toBeDefined(); + expect(a.renderState).toEqual(Appearance.getDefaultRenderState(true, true)); + expect(a.vertexFormat).toEqual(EllipsoidSurfaceAppearance.VERTEX_FORMAT); + expect(a.flat).toEqual(false); + expect(a.faceForward).toEqual(false); + expect(a.translucent).toEqual(true); + expect(a.aboveGround).toEqual(false); + }); + +}); diff --git a/Specs/Scene/ExtentPrimitiveSpec.js b/Specs/Scene/ExtentPrimitiveSpec.js new file mode 100644 index 000000000000..8c7bfd0d4b60 --- /dev/null +++ b/Specs/Scene/ExtentPrimitiveSpec.js @@ -0,0 +1,226 @@ +/*global defineSuite*/ +defineSuite([ + 'Scene/ExtentPrimitive', + 'Specs/createContext', + 'Specs/destroyContext', + 'Specs/createCamera', + 'Specs/createFrameState', + 'Specs/frameState', + 'Specs/pick', + 'Specs/render', + 'Core/BoundingSphere', + 'Core/Cartesian3', + 'Core/Cartographic', + 'Core/Ellipsoid', + 'Core/Extent', + 'Core/Math', + 'Renderer/ClearCommand', + 'Scene/SceneMode' + ], function( + ExtentPrimitive, + createContext, + destroyContext, + createCamera, + createFrameState, + frameState, + pick, + render, + BoundingSphere, + Cartesian3, + Cartographic, + Ellipsoid, + Extent, + CesiumMath, + ClearCommand, + SceneMode) { + "use strict"; + /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/ + + var context; + var extent; + var us; + + beforeAll(function() { + context = createContext(); + }); + + afterAll(function() { + destroyContext(context); + }); + + beforeEach(function() { + extent = new ExtentPrimitive(); + + us = context.getUniformState(); + us.update(createFrameState(createCamera(context, new Cartesian3(1.02, 0.0, 0.0), Cartesian3.ZERO, Cartesian3.UNIT_Z))); + }); + + afterEach(function() { + extent = extent && extent.destroy(); + us = undefined; + }); + + function createExtent() { + var ellipsoid = Ellipsoid.UNIT_SPHERE; + + var e = new ExtentPrimitive({ + ellipsoid : ellipsoid, + granularity : CesiumMath.toRadians(20.0), + extent : Extent.fromDegrees(-50.0, -50.0, 50.0, 50.0) + }); + + return e; + } + + it('gets default show', function() { + expect(extent.show).toEqual(true); + }); + + it('gets the default color', function() { + expect(extent.material.uniforms.color).toEqual({ + red : 1.0, + green : 1.0, + blue : 0.0, + alpha : 0.5 + }); + }); + + it('has a default ellipsoid', function() { + expect(extent.ellipsoid).toEqual(Ellipsoid.WGS84); + }); + + it('gets the default granularity', function() { + expect(extent.granularity).toEqual(CesiumMath.toRadians(1.0)); + }); + + it('renders', function() { + extent = createExtent(); + extent.material.uniforms.color = { + red : 1.0, + green : 0.0, + blue : 0.0, + alpha : 1.0 + }; + + ClearCommand.ALL.execute(context); + expect(context.readPixels()).toEqual([0, 0, 0, 0]); + + render(context, frameState, extent); + expect(context.readPixels()).not.toEqual([0, 0, 0, 0]); + }); + + it('does not render when show is false', function() { + extent = createExtent(); + extent.material.uniforms.color = { + red : 1.0, + green : 0.0, + blue : 0.0, + alpha : 1.0 + }; + extent.show = false; + + expect(render(context, frameState, extent)).toEqual(0); + }); + + it('does not render without extent', function() { + extent = new ExtentPrimitive(); + extent.ellipsoid = Ellipsoid.UNIT_SPHERE; + extent.granularity = CesiumMath.toRadians(20.0); + expect(render(context, frameState, extent)).toEqual(0); + }); + + it('is picked', function() { + extent = createExtent(); + + var pickedObject = pick(context, frameState, extent, 0, 0); + expect(pickedObject).toEqual(extent); + }); + + it('is not picked (show === false)', function() { + extent = createExtent(); + extent.show = false; + + var pickedObject = pick(context, frameState, extent, 0, 0); + expect(pickedObject).not.toBeDefined(); + }); + + it('is not picked (alpha === 0.0)', function() { + extent = createExtent(); + extent.material.uniforms.color.alpha = 0.0; + + var pickedObject = pick(context, frameState, extent, 0, 0); + expect(pickedObject).not.toBeDefined(); + }); + + it('test 3D bounding sphere', function() { + extent = createExtent(); + var commandList = []; + extent.update(context, frameState, commandList); + var boundingVolume = commandList[0].colorList[0].boundingVolume; + expect(boundingVolume).toEqual(BoundingSphere.fromExtent3D(extent.extent, Ellipsoid.UNIT_SPHERE)); + }); + + it('test Columbus view bounding sphere', function() { + extent = createExtent(); + + var mode = frameState.mode; + frameState.mode = SceneMode.COLUMBUS_VIEW; + var commandList = []; + extent.update(context, frameState, commandList); + var boundingVolume = commandList[0].colorList[0].boundingVolume; + frameState.mode = mode; + + var b3D = BoundingSphere.fromExtent3D(extent.extent, Ellipsoid.UNIT_SPHERE); + expect(boundingVolume).toEqual(BoundingSphere.projectTo2D(b3D, frameState.scene2D.projection)); + }); + + it('test 2D bounding sphere', function() { + extent = createExtent(); + + var mode = frameState.mode; + frameState.mode = SceneMode.SCENE2D; + var commandList = []; + extent.update(context, frameState, commandList); + var boundingVolume = commandList[0].colorList[0].boundingVolume; + frameState.mode = mode; + + var b3D = BoundingSphere.fromExtent3D(extent.extent, Ellipsoid.UNIT_SPHERE); + var b2D = BoundingSphere.projectTo2D(b3D, frameState.scene2D.projection); + b2D.center.x = 0.0; + expect(boundingVolume).toEqual(b2D); + }); + + it('isDestroyed', function() { + var e = new ExtentPrimitive(); + expect(e.isDestroyed()).toEqual(false); + e.destroy(); + expect(e.isDestroyed()).toEqual(true); + }); + + it('throws when updated/rendered without a ellipsoid', function() { + extent = createExtent(); + extent.ellipsoid = undefined; + + expect(function() { + extent.update(context, frameState); + }).toThrow(); + }); + + it('throws when updated/rendered without an invalid granularity', function() { + extent = createExtent(); + extent.granularity = -1.0; + + expect(function() { + extent.update(context, frameState); + }).toThrow(); + }); + + it('throws when rendered without a material', function() { + extent = createExtent(); + extent.material = undefined; + + expect(function() { + render(context, frameState, extent); + }).toThrow(); + }); +}, 'WebGL'); diff --git a/Specs/Scene/PolygonSpec.js b/Specs/Scene/PolygonSpec.js index 4cfe1137bd54..63bb0bba1dd9 100644 --- a/Specs/Scene/PolygonSpec.js +++ b/Specs/Scene/PolygonSpec.js @@ -8,15 +8,11 @@ defineSuite([ 'Specs/frameState', 'Specs/pick', 'Specs/render', - 'Core/BoundingRectangle', 'Core/BoundingSphere', 'Core/Cartesian3', 'Core/Cartographic', 'Core/Ellipsoid', - 'Core/Extent', - 'Core/Matrix4', 'Core/Math', - 'Core/JulianDate', 'Renderer/ClearCommand', 'Scene/SceneMode' ], function( @@ -28,15 +24,11 @@ defineSuite([ frameState, pick, render, - BoundingRectangle, BoundingSphere, Cartesian3, Cartographic, Ellipsoid, - Extent, - Matrix4, CesiumMath, - JulianDate, ClearCommand, SceneMode) { "use strict"; From 53969f840c5140331bfd8caa9044a44f3c3319e4 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Tue, 2 Jul 2013 16:01:54 -0400 Subject: [PATCH 285/306] Add appearance rendering tests. --- Source/Scene/MaterialAppearance.js | 1 - Source/Scene/Primitive.js | 1 - Specs/Scene/DebugAppearanceSpec.js | 225 +++++++++++++++++- Specs/Scene/EllipsoidSurfaceAppearanceSpec.js | 68 +++++- Specs/Scene/MaterialAppearanceSpec.js | 129 ++++++++++ Specs/Scene/PerInstanceColorAppearanceSpec.js | 106 +++++++++ 6 files changed, 524 insertions(+), 6 deletions(-) create mode 100644 Specs/Scene/MaterialAppearanceSpec.js create mode 100644 Specs/Scene/PerInstanceColorAppearanceSpec.js diff --git a/Source/Scene/MaterialAppearance.js b/Source/Scene/MaterialAppearance.js index e00152017dfe..9126016e5039 100644 --- a/Source/Scene/MaterialAppearance.js +++ b/Source/Scene/MaterialAppearance.js @@ -213,7 +213,6 @@ define([ vertexFormat : VertexFormat.POSITION_AND_NORMAL, vertexShaderSource : BasicMaterialAppearanceVS, fragmentShaderSource : BasicMaterialAppearanceFS - }), /** * Materials with textures, which require position, diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index f43631352f75..6b5ab2bff7b2 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -683,7 +683,6 @@ define([ var createSP = false; if (this._appearance !== appearance) { - this._appearance = appearance; this._material = material; createRS = true; diff --git a/Specs/Scene/DebugAppearanceSpec.js b/Specs/Scene/DebugAppearanceSpec.js index 140feae65580..faa968cc28fb 100644 --- a/Specs/Scene/DebugAppearanceSpec.js +++ b/Specs/Scene/DebugAppearanceSpec.js @@ -1,13 +1,66 @@ /*global defineSuite*/ defineSuite([ 'Scene/DebugAppearance', - 'Scene/Appearance' + 'Scene/Appearance', + 'Scene/Primitive', + 'Core/ExtentGeometry', + 'Core/Extent', + 'Core/GeometryInstance', + 'Core/GeometryInstanceAttribute', + 'Core/ComponentDatatype', + 'Core/VertexFormat', + 'Renderer/ClearCommand', + 'Specs/render', + 'Specs/createCanvas', + 'Specs/destroyCanvas', + 'Specs/createContext', + 'Specs/destroyContext', + 'Specs/createFrameState' ], function( DebugAppearance, - Appearance) { + Appearance, + Primitive, + ExtentGeometry, + Extent, + GeometryInstance, + GeometryInstanceAttribute, + ComponentDatatype, + VertexFormat, + ClearCommand, + render, + createCanvas, + destroyCanvas, + createContext, + destroyContext, + createFrameState) { "use strict"; /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/ + var context; + var frameState; + var extentInstance; + + beforeAll(function() { + context = createContext(); + frameState = createFrameState(); + + var extent = Extent.fromDegrees(-80.0, 20.0, -70.0, 40.0); + extentInstance = new GeometryInstance({ + geometry : new ExtentGeometry({ + vertexFormat : VertexFormat.ALL, + extent : extent + }) + }); + + frameState.camera.controller.viewExtent(extent); + var us = context.getUniformState(); + us.update(frameState); + }); + + afterAll(function() { + destroyContext(context); + }); + it('constructor throws without attributeName', function() { expect(function() { return new DebugAppearance(); @@ -116,4 +169,172 @@ defineSuite([ }).toThrow(); }); + it('renders normal', function() { + var primitive = new Primitive({ + geometryInstances : extentInstance, + appearance : new DebugAppearance({ + attributeName : 'normal' + }) + }); + + ClearCommand.ALL.execute(context); + expect(context.readPixels()).toEqual([0, 0, 0, 0]); + + render(context, frameState, primitive); + expect(context.readPixels()).not.toEqual([0, 0, 0, 0]); + + primitive = primitive && primitive.destroy(); + }); + + it('renders binormal', function() { + var primitive = new Primitive({ + geometryInstances : extentInstance, + appearance : new DebugAppearance({ + attributeName : 'binormal' + }) + }); + + ClearCommand.ALL.execute(context); + expect(context.readPixels()).toEqual([0, 0, 0, 0]); + + render(context, frameState, primitive); + expect(context.readPixels()).not.toEqual([0, 0, 0, 0]); + + primitive = primitive && primitive.destroy(); + }); + + it('renders tangent', function() { + var primitive = new Primitive({ + geometryInstances : extentInstance, + appearance : new DebugAppearance({ + attributeName : 'tangent' + }) + }); + + ClearCommand.ALL.execute(context); + expect(context.readPixels()).toEqual([0, 0, 0, 0]); + + render(context, frameState, primitive); + expect(context.readPixels()).not.toEqual([0, 0, 0, 0]); + + primitive = primitive && primitive.destroy(); + }); + + it('renders st', function() { + var primitive = new Primitive({ + geometryInstances : extentInstance, + appearance : new DebugAppearance({ + attributeName : 'st' + }) + }); + + ClearCommand.ALL.execute(context); + expect(context.readPixels()).toEqual([0, 0, 0, 0]); + + render(context, frameState, primitive); + expect(context.readPixels()).not.toEqual([0, 0, 0, 0]); + + primitive = primitive && primitive.destroy(); + }); + + it('renders float', function() { + extentInstance.attributes = { + debug : new GeometryInstanceAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 1, + value : [1.0] + }) + }; + var primitive = new Primitive({ + geometryInstances : extentInstance, + appearance : new DebugAppearance({ + attributeName : 'debug', + glslDatatype : 'float' + }) + }); + + ClearCommand.ALL.execute(context); + expect(context.readPixels()).toEqual([0, 0, 0, 0]); + + render(context, frameState, primitive); + expect(context.readPixels()).not.toEqual([0, 0, 0, 0]); + + primitive = primitive && primitive.destroy(); + }); + + it('renders vec2', function() { + extentInstance.attributes = { + debug : new GeometryInstanceAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 2, + value : [1.0, 2.0] + }) + }; + var primitive = new Primitive({ + geometryInstances : extentInstance, + appearance : new DebugAppearance({ + attributeName : 'debug', + glslDatatype : 'vec2' + }) + }); + + ClearCommand.ALL.execute(context); + expect(context.readPixels()).toEqual([0, 0, 0, 0]); + + render(context, frameState, primitive); + expect(context.readPixels()).not.toEqual([0, 0, 0, 0]); + + primitive = primitive && primitive.destroy(); + }); + + it('renders vec3', function() { + extentInstance.attributes = { + debug : new GeometryInstanceAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + value : [1.0, 2.0, 3.0] + }) + }; + var primitive = new Primitive({ + geometryInstances : extentInstance, + appearance : new DebugAppearance({ + attributeName : 'debug', + glslDatatype : 'vec3' + }) + }); + + ClearCommand.ALL.execute(context); + expect(context.readPixels()).toEqual([0, 0, 0, 0]); + + render(context, frameState, primitive); + expect(context.readPixels()).not.toEqual([0, 0, 0, 0]); + + primitive = primitive && primitive.destroy(); + }); + + it('renders vec4', function() { + extentInstance.attributes = { + debug : new GeometryInstanceAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + value : [1.0, 2.0, 3.0, 4.0] + }) + }; + var primitive = new Primitive({ + geometryInstances : extentInstance, + appearance : new DebugAppearance({ + attributeName : 'debug', + glslDatatype : 'vec4' + }) + }); + + ClearCommand.ALL.execute(context); + expect(context.readPixels()).toEqual([0, 0, 0, 0]); + + render(context, frameState, primitive); + expect(context.readPixels()).not.toEqual([0, 0, 0, 0]); + + primitive = primitive && primitive.destroy(); + }); + }); diff --git a/Specs/Scene/EllipsoidSurfaceAppearanceSpec.js b/Specs/Scene/EllipsoidSurfaceAppearanceSpec.js index b3c9c3acd596..0fe4ad7fb27d 100644 --- a/Specs/Scene/EllipsoidSurfaceAppearanceSpec.js +++ b/Specs/Scene/EllipsoidSurfaceAppearanceSpec.js @@ -2,14 +2,68 @@ defineSuite([ 'Scene/EllipsoidSurfaceAppearance', 'Scene/Appearance', - 'Scene/Material' + 'Scene/Material', + 'Scene/Primitive', + 'Core/ExtentGeometry', + 'Core/Extent', + 'Core/GeometryInstance', + 'Core/ColorGeometryInstanceAttribute', + 'Renderer/ClearCommand', + 'Specs/render', + 'Specs/createCanvas', + 'Specs/destroyCanvas', + 'Specs/createContext', + 'Specs/destroyContext', + 'Specs/createFrameState' ], function( EllipsoidSurfaceAppearance, Appearance, - Material) { + Material, + Primitive, + ExtentGeometry, + Extent, + GeometryInstance, + ColorGeometryInstanceAttribute, + ClearCommand, + render, + createCanvas, + destroyCanvas, + createContext, + destroyContext, + createFrameState) { "use strict"; /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/ + var context; + var frameState; + var primitive; + + beforeAll(function() { + context = createContext(); + frameState = createFrameState(); + + var extent = Extent.fromDegrees(-80.0, 20.0, -70.0, 40.0); + primitive = new Primitive({ + geometryInstances : new GeometryInstance({ + geometry : new ExtentGeometry({ + extent : extent + }), + attributes : { + color : new ColorGeometryInstanceAttribute(1.0, 1.0, 0.0, 1.0) + } + }) + }); + + frameState.camera.controller.viewExtent(extent); + var us = context.getUniformState(); + us.update(frameState); + }); + + afterAll(function() { + primitive = primitive && primitive.destroy(); + destroyContext(context); + }); + it('constructor', function() { var a = new EllipsoidSurfaceAppearance(); @@ -25,4 +79,14 @@ defineSuite([ expect(a.aboveGround).toEqual(false); }); + it('renders', function() { + primitive.appearance = new EllipsoidSurfaceAppearance(); + + ClearCommand.ALL.execute(context); + expect(context.readPixels()).toEqual([0, 0, 0, 0]); + + render(context, frameState, primitive); + expect(context.readPixels()).not.toEqual([0, 0, 0, 0]); + }); + }); diff --git a/Specs/Scene/MaterialAppearanceSpec.js b/Specs/Scene/MaterialAppearanceSpec.js new file mode 100644 index 000000000000..b7781a13bc8d --- /dev/null +++ b/Specs/Scene/MaterialAppearanceSpec.js @@ -0,0 +1,129 @@ +/*global defineSuite*/ +defineSuite([ + 'Scene/MaterialAppearance', + 'Scene/Appearance', + 'Scene/Material', + 'Scene/Primitive', + 'Core/ExtentGeometry', + 'Core/Extent', + 'Core/GeometryInstance', + 'Core/ColorGeometryInstanceAttribute', + 'Renderer/ClearCommand', + 'Specs/render', + 'Specs/createCanvas', + 'Specs/destroyCanvas', + 'Specs/createContext', + 'Specs/destroyContext', + 'Specs/createFrameState' + ], function( + MaterialAppearance, + Appearance, + Material, + Primitive, + ExtentGeometry, + Extent, + GeometryInstance, + ColorGeometryInstanceAttribute, + ClearCommand, + render, + createCanvas, + destroyCanvas, + createContext, + destroyContext, + createFrameState) { + "use strict"; + /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/ + + var context; + var frameState; + var primitive; + + beforeAll(function() { + context = createContext(); + frameState = createFrameState(); + + var extent = Extent.fromDegrees(-80.0, 20.0, -70.0, 40.0); + primitive = new Primitive({ + geometryInstances : new GeometryInstance({ + geometry : new ExtentGeometry({ + vertexFormat : MaterialAppearance.MaterialSupport.ALL.vertexFormat, + extent : extent + }), + attributes : { + color : new ColorGeometryInstanceAttribute(1.0, 1.0, 0.0, 1.0) + } + }) + }); + + frameState.camera.controller.viewExtent(extent); + var us = context.getUniformState(); + us.update(frameState); + }); + + afterAll(function() { + primitive = primitive && primitive.destroy(); + destroyContext(context); + }); + + it('constructor', function() { + var a = new MaterialAppearance(); + + expect(a.materialSupport).toEqual(MaterialAppearance.MaterialSupport.TEXTURED); + expect(a.material).toBeDefined(); + expect(a.material.type).toEqual(Material.ColorType); + expect(a.vertexShaderSource).toEqual(MaterialAppearance.MaterialSupport.TEXTURED.vertexShaderSource); + expect(a.fragmentShaderSource).toEqual(MaterialAppearance.MaterialSupport.TEXTURED.fragmentShaderSource); + expect(a.renderState).toEqual(Appearance.getDefaultRenderState(true, false)); + expect(a.vertexFormat).toEqual(MaterialAppearance.MaterialSupport.TEXTURED.vertexFormat); + expect(a.flat).toEqual(false); + expect(a.faceForward).toEqual(false); + expect(a.translucent).toEqual(true); + expect(a.closed).toEqual(false); + }); + + it('renders basic', function() { + primitive.appearance = new MaterialAppearance({ + materialSupport : MaterialAppearance.MaterialSupport.BASIC, + translucent : false, + closed : true, + material : Material.fromType(context, Material.DotType) + }); + + ClearCommand.ALL.execute(context); + expect(context.readPixels()).toEqual([0, 0, 0, 0]); + + render(context, frameState, primitive); + expect(context.readPixels()).not.toEqual([0, 0, 0, 0]); + }); + + it('renders textured', function() { + primitive.appearance = new MaterialAppearance({ + materialSupport : MaterialAppearance.MaterialSupport.TEXTURED, + translucent : false, + closed : true, + material : Material.fromType(context, Material.ImageType) + }); + + ClearCommand.ALL.execute(context); + expect(context.readPixels()).toEqual([0, 0, 0, 0]); + + render(context, frameState, primitive); + expect(context.readPixels()).not.toEqual([0, 0, 0, 0]); + }); + + it('renders all', function() { + primitive.appearance = new MaterialAppearance({ + materialSupport : MaterialAppearance.MaterialSupport.ALL, + translucent : false, + closed : true, + material : Material.fromType(context, Material.NormalMapType) + }); + + ClearCommand.ALL.execute(context); + expect(context.readPixels()).toEqual([0, 0, 0, 0]); + + render(context, frameState, primitive); + expect(context.readPixels()).not.toEqual([0, 0, 0, 0]); + }); + +}); diff --git a/Specs/Scene/PerInstanceColorAppearanceSpec.js b/Specs/Scene/PerInstanceColorAppearanceSpec.js new file mode 100644 index 000000000000..71e1050a0e66 --- /dev/null +++ b/Specs/Scene/PerInstanceColorAppearanceSpec.js @@ -0,0 +1,106 @@ +/*global defineSuite*/ +defineSuite([ + 'Scene/PerInstanceColorAppearance', + 'Scene/Appearance', + 'Scene/Material', + 'Scene/Primitive', + 'Core/ExtentGeometry', + 'Core/Extent', + 'Core/GeometryInstance', + 'Core/ColorGeometryInstanceAttribute', + 'Renderer/ClearCommand', + 'Specs/render', + 'Specs/createCanvas', + 'Specs/destroyCanvas', + 'Specs/createContext', + 'Specs/destroyContext', + 'Specs/createFrameState' + ], function( + PerInstanceColorAppearance, + Appearance, + Material, + Primitive, + ExtentGeometry, + Extent, + GeometryInstance, + ColorGeometryInstanceAttribute, + ClearCommand, + render, + createCanvas, + destroyCanvas, + createContext, + destroyContext, + createFrameState) { + "use strict"; + /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/ + + var context; + var frameState; + var primitive; + + beforeAll(function() { + context = createContext(); + frameState = createFrameState(); + + var extent = Extent.fromDegrees(-80.0, 20.0, -70.0, 40.0); + primitive = new Primitive({ + geometryInstances : new GeometryInstance({ + geometry : new ExtentGeometry({ + vertexFormat : PerInstanceColorAppearance.VERTEX_FORMAT, + extent : extent + }), + attributes : { + color : new ColorGeometryInstanceAttribute(1.0, 1.0, 0.0, 1.0) + } + }) + }); + + frameState.camera.controller.viewExtent(extent); + var us = context.getUniformState(); + us.update(frameState); + }); + + afterAll(function() { + primitive = primitive && primitive.destroy(); + destroyContext(context); + }); + + it('constructor', function() { + var a = new PerInstanceColorAppearance(); + + expect(a.material).not.toBeDefined(); + expect(a.vertexShaderSource).toBeDefined(); + expect(a.fragmentShaderSource).toBeDefined(); + expect(a.renderState).toEqual(Appearance.getDefaultRenderState(true, false)); + expect(a.vertexFormat).toEqual(PerInstanceColorAppearance.VERTEX_FORMAT); + expect(a.flat).toEqual(false); + expect(a.faceForward).toEqual(false); + expect(a.translucent).toEqual(true); + expect(a.closed).toEqual(false); + }); + + it('renders', function() { + primitive.appearance = new PerInstanceColorAppearance(); + + ClearCommand.ALL.execute(context); + expect(context.readPixels()).toEqual([0, 0, 0, 0]); + + render(context, frameState, primitive); + expect(context.readPixels()).not.toEqual([0, 0, 0, 0]); + }); + + it('renders flat', function() { + primitive.appearance = new PerInstanceColorAppearance({ + flat : true, + translucent : false, + closed : true + }); + + ClearCommand.ALL.execute(context); + expect(context.readPixels()).toEqual([0, 0, 0, 0]); + + render(context, frameState, primitive); + expect(context.readPixels()).not.toEqual([0, 0, 0, 0]); + }); + +}); From 2e113befa45c104ccc21203d1190a16a9941586f Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Tue, 2 Jul 2013 21:09:44 -0400 Subject: [PATCH 286/306] Add Primitive and createTangentSpaceDebugPrimitive tests. --- Source/Scene/Primitive.js | 11 +- Specs/Scene/PrimitiveSpec.js | 613 ++++++++++++++++++ .../createTangentSpaceDebugPrimitiveSpec.js | 63 ++ 3 files changed, 686 insertions(+), 1 deletion(-) create mode 100644 Specs/Scene/PrimitiveSpec.js create mode 100644 Specs/Scene/createTangentSpaceDebugPrimitiveSpec.js diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index 6b5ab2bff7b2..1b5f9b559b72 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -819,9 +819,10 @@ define([ * * @param {Object} id The id of the {@link GeometryInstance}. * - * @returns {Object} The typed array in the attribute's format. + * @returns {Object} The typed array in the attribute's format or undefined if the is no instance with id. * * @exception {DeveloperError} id is required. + * @exception {DeveloperError} must call update before calling getGeometryInstanceAttributes. * * @example * var attributes = primitive.getGeometryInstanceAttributes('an id'); @@ -838,7 +839,15 @@ define([ return cachedObject; } + if (typeof this._perInstanceAttributes === 'undefined') { + throw new DeveloperError('must call update before calling getGeometryInstanceAttributes'); + } + var perInstanceAttributes = this._perInstanceAttributes[id]; + if (typeof perInstanceAttributes === 'undefined') { + return undefined; + } + var attributes = {}; for (var name in perInstanceAttributes) { diff --git a/Specs/Scene/PrimitiveSpec.js b/Specs/Scene/PrimitiveSpec.js new file mode 100644 index 000000000000..c295760a6c81 --- /dev/null +++ b/Specs/Scene/PrimitiveSpec.js @@ -0,0 +1,613 @@ +/*global defineSuite*/ +defineSuite([ + 'Scene/Primitive', + 'Core/ExtentGeometry', + 'Core/Geometry', + 'Core/GeometryAttribute', + 'Core/GeometryInstance', + 'Core/ColorGeometryInstanceAttribute', + 'Core/ShowGeometryInstanceAttribute', + 'Core/GeometryInstanceAttribute', + 'Core/ComponentDatatype', + 'Core/Cartesian3', + 'Core/Matrix4', + 'Core/Extent', + 'Core/Ellipsoid', + 'Core/PrimitiveType', + 'Renderer/ClearCommand', + 'Scene/MaterialAppearance', + 'Scene/PerInstanceColorAppearance', + 'Scene/SceneMode', + 'Scene/OrthographicFrustum', + 'Scene/Camera', + 'Specs/render', + 'Specs/pick', + 'Specs/createCanvas', + 'Specs/destroyCanvas', + 'Specs/createContext', + 'Specs/destroyContext', + 'Specs/createFrameState' + ], function( + Primitive, + ExtentGeometry, + Geometry, + GeometryAttribute, + GeometryInstance, + ColorGeometryInstanceAttribute, + ShowGeometryInstanceAttribute, + GeometryInstanceAttribute, + ComponentDatatype, + Cartesian3, + Matrix4, + Extent, + Ellipsoid, + PrimitiveType, + ClearCommand, + MaterialAppearance, + PerInstanceColorAppearance, + SceneMode, + OrthographicFrustum, + Camera, + render, + pick, + createCanvas, + destroyCanvas, + createContext, + destroyContext, + createFrameState) { + "use strict"; + /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/ + + var context; + var frameState; + var us; + + var ellipsoid; + + var extent1; + var extent2; + + var extentInstance1; + var extentInstance2; + + beforeAll(function() { + context = createContext(); + frameState = createFrameState(new Camera(context.getCanvas())); + + us = context.getUniformState(); + us.update(frameState); + + ellipsoid = Ellipsoid.WGS84; + }); + + afterAll(function() { + destroyContext(context); + }); + + beforeEach(function() { + extent1 = Extent.fromDegrees(-80.0, 20.0, -70.0, 30.0); + extent2 = Extent.fromDegrees(70.0, 20.0, 80.0, 30.0); + + var translation = ellipsoid.cartographicToCartesian(extent1.getCenter()).normalize().multiplyByScalar(2.0); + extentInstance1 = new GeometryInstance({ + geometry : new ExtentGeometry({ + vertexFormat : PerInstanceColorAppearance.VERTEX_FORMAT, + ellipsoid : ellipsoid, + extent : extent1 + }), + modelMatrix : Matrix4.fromTranslation(translation), + id : 'extent1', + attributes : { + color : new ColorGeometryInstanceAttribute(1.0, 1.0, 0.0, 1.0), + show : new ShowGeometryInstanceAttribute(true) + } + }); + + translation = ellipsoid.cartographicToCartesian(extent2.getCenter()).normalize().multiplyByScalar(3.0); + extentInstance2 = new GeometryInstance({ + geometry : new ExtentGeometry({ + vertexFormat : PerInstanceColorAppearance.VERTEX_FORMAT, + ellipsoid : ellipsoid, + extent : extent2 + }), + modelMatrix : Matrix4.fromTranslation(translation), + id : 'extent2', + attributes : { + color : new ColorGeometryInstanceAttribute(0.0, 1.0, 1.0, 1.0), + show : new ShowGeometryInstanceAttribute(true) + } + }); + }); + + it('default constructs', function() { + var primitive = new Primitive(); + expect(primitive.geometryInstances).not.toBeDefined(); + expect(primitive.appearance).not.toBeDefined(); + expect(primitive.modelMatrix).toEqual(Matrix4.IDENTITY); + expect(primitive.show).toEqual(true); + }); + + it('releases geometry instances when releaseGeometryInstances is true', function() { + var primitive = new Primitive({ + geometryInstances : [extentInstance1, extentInstance2], + appearance : new PerInstanceColorAppearance(), + releaseGeometryInstances : true + }); + + expect(primitive.geometryInstances).toBeDefined(); + primitive.update(context, frameState, []); + expect(primitive.geometryInstances).not.toBeDefined(); + + primitive = primitive && primitive.destroy(); + }); + + it('does not release geometry instances when releaseGeometryInstances is false', function() { + var primitive = new Primitive({ + geometryInstances : [extentInstance1, extentInstance2], + appearance : new PerInstanceColorAppearance(), + releaseGeometryInstances : false + }); + + expect(primitive.geometryInstances).toBeDefined(); + primitive.update(context, frameState, []); + expect(primitive.geometryInstances).toBeDefined(); + + primitive = primitive && primitive.destroy(); + }); + + it('does not render when show is false', function() { + var primitive = new Primitive({ + geometryInstances : [extentInstance1, extentInstance2], + appearance : new PerInstanceColorAppearance(), + allowColumbusView : false + }); + + var commands = []; + primitive.update(context, frameState, commands); + expect(commands.length).toBeGreaterThan(0); + + commands.length = 0; + primitive.show = false; + primitive.update(context, frameState, commands); + expect(commands.length).toEqual(0); + + primitive = primitive && primitive.destroy(); + }); + + it('does not render other than for the color or pick pass', function() { + var primitive = new Primitive({ + geometryInstances : [extentInstance1, extentInstance2], + appearance : new PerInstanceColorAppearance(), + allowColumbusView : false + }); + + frameState.passes.color = false; + frameState.passes.pick = false; + + var commands = []; + primitive.update(context, frameState, commands); + expect(commands.length).toEqual(0); + + frameState.passes.color = true; + frameState.passes.pick = true; + + primitive = primitive && primitive.destroy(); + }); + + it('does not render when allowColumbusView is false and the scene mode is SCENE2D', function() { + var primitive = new Primitive({ + geometryInstances : [extentInstance1, extentInstance2], + appearance : new PerInstanceColorAppearance(), + allowColumbusView : false + }); + + frameState.mode = SceneMode.SCENE2D; + + var commands = []; + primitive.update(context, frameState, commands); + expect(commands.length).toEqual(0); + + frameState.mode = SceneMode.SCENE3D; + primitive = primitive && primitive.destroy(); + }); + + it('does not render when allowColumbusView is false and the scene mode is COLUMBUS_VIEW', function() { + var primitive = new Primitive({ + geometryInstances : [extentInstance1, extentInstance2], + appearance : new PerInstanceColorAppearance(), + allowColumbusView : false + }); + + frameState.mode = SceneMode.COLUMBUS_VIEW; + + var commands = []; + primitive.update(context, frameState, commands); + expect(commands.length).toEqual(0); + + frameState.mode = SceneMode.SCENE3D; + primitive = primitive && primitive.destroy(); + }); + + /* + it('renders in Columbus view when allowColumbusView is true', function() { + var primitive = new Primitive({ + geometryInstances : [extentInstance1, extentInstance2], + appearance : new PerInstanceColorAppearance(), + allowColumbusView : true + }); + + frameState.mode = SceneMode.COLUMBUS_VIEW; + frameState.camera.transform = new Matrix4(0.0, 0.0, 1.0, 0.0, + 1.0, 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 1.0); + frameState.camera.controller.update(frameState.mode, frameState.scene2D); + + frameState.camera.controller.viewExtent(extent1); + us.update(frameState); + + ClearCommand.ALL.execute(context); + expect(context.readPixels()).toEqual([0, 0, 0, 0]); + + render(context, frameState, primitive); + expect(context.readPixels()).not.toEqual([0, 0, 0, 0]); + + frameState.camera.controller.viewExtent(extent2); + us.update(frameState); + + ClearCommand.ALL.execute(context); + expect(context.readPixels()).toEqual([0, 0, 0, 0]); + + render(context, frameState, primitive); + expect(context.readPixels()).not.toEqual([0, 0, 0, 0]); + + frameState = createFrameState(); // reset frame state + primitive = primitive && primitive.destroy(); + }); + + it('renders in 2D when allowColumbusView is true', function() { + var primitive = new Primitive({ + geometryInstances : [extentInstance1, extentInstance2], + appearance : new PerInstanceColorAppearance(), + allowColumbusView : true + }); + + frameState.mode = SceneMode.SCENE2D; + frameState.camera.transform = new Matrix4(0.0, 0.0, 1.0, 0.0, + 1.0, 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 1.0); + var frustum = new OrthographicFrustum(); + frustum.right = Ellipsoid.WGS84.getMaximumRadius() * Math.PI; + frustum.left = -frustum.right; + frustum.top = frustum.right; + frustum.bottom = -frustum.top; + frameState.camera.frustum = frustum; + frameState.camera.controller.update(frameState.mode, frameState.scene2D); + + frameState.camera.controller.viewExtent(extent1); + us.update(frameState); + + ClearCommand.ALL.execute(context); + expect(context.readPixels()).toEqual([0, 0, 0, 0]); + + render(context, frameState, primitive); + expect(context.readPixels()).not.toEqual([0, 0, 0, 0]); + + frameState.camera.controller.viewExtent(extent2); + us.update(frameState); + + ClearCommand.ALL.execute(context); + expect(context.readPixels()).toEqual([0, 0, 0, 0]); + + render(context, frameState, primitive); + expect(context.readPixels()).not.toEqual([0, 0, 0, 0]); + + frameState = createFrameState(); // reset frame state + primitive = primitive && primitive.destroy(); + }); + */ + + it('transforms to world coordinates', function() { + var primitive = new Primitive({ + geometryInstances : [extentInstance1, extentInstance2], + appearance : new PerInstanceColorAppearance(), + allowColumbusView : false + }); + + frameState.camera.controller.viewExtent(extent1); + us.update(frameState); + + ClearCommand.ALL.execute(context); + expect(context.readPixels()).toEqual([0, 0, 0, 0]); + + render(context, frameState, primitive); + expect(context.readPixels()).not.toEqual([0, 0, 0, 0]); + + frameState.camera.controller.viewExtent(extent2); + us.update(frameState); + + ClearCommand.ALL.execute(context); + expect(context.readPixels()).toEqual([0, 0, 0, 0]); + + render(context, frameState, primitive); + expect(context.readPixels()).not.toEqual([0, 0, 0, 0]); + + expect(primitive.modelMatrix).toEqual(Matrix4.IDENTITY); + + primitive = primitive && primitive.destroy(); + }); + + it('does not transform to world coordinates', function() { + extentInstance2.modelMatrix = Matrix4.clone(extentInstance1.modelMatrix); + var primitive = new Primitive({ + geometryInstances : [extentInstance1, extentInstance2], + appearance : new PerInstanceColorAppearance(), + allowColumbusView : false + }); + + frameState.camera.controller.viewExtent(extent1); + us.update(frameState); + + ClearCommand.ALL.execute(context); + expect(context.readPixels()).toEqual([0, 0, 0, 0]); + + render(context, frameState, primitive); + expect(context.readPixels()).not.toEqual([0, 0, 0, 0]); + + frameState.camera.controller.viewExtent(extent2); + us.update(frameState); + + ClearCommand.ALL.execute(context); + expect(context.readPixels()).toEqual([0, 0, 0, 0]); + + render(context, frameState, primitive); + expect(context.readPixels()).not.toEqual([0, 0, 0, 0]); + + expect(primitive.modelMatrix).not.toEqual(Matrix4.IDENTITY); + + primitive = primitive && primitive.destroy(); + }); + + it('get common per instance attributes', function() { + extentInstance2.attributes.not_used = new GeometryInstanceAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 1, + value : [0.5] + }); + + var primitive = new Primitive({ + geometryInstances : [extentInstance1, extentInstance2], + appearance : new PerInstanceColorAppearance(), + allowColumbusView : false + }); + primitive.update(context, frameState, []); + + var attributes = primitive.getGeometryInstanceAttributes('extent1'); + expect(attributes.color).toBeDefined(); + expect(attributes.show).toBeDefined(); + + attributes = primitive.getGeometryInstanceAttributes('extent2'); + expect(attributes.color).toBeDefined(); + expect(attributes.show).toBeDefined(); + expect(attributes.not_used).not.toBeDefined(); + + primitive = primitive && primitive.destroy(); + }); + + it('modify color instance attribute', function() { + var primitive = new Primitive({ + geometryInstances : extentInstance1, + appearance : new PerInstanceColorAppearance(), + allowColumbusView : false + }); + + frameState.camera.controller.viewExtent(extent1); + us.update(frameState); + + ClearCommand.ALL.execute(context); + expect(context.readPixels()).toEqual([0, 0, 0, 0]); + + render(context, frameState, primitive); + var pixels = context.readPixels(); + expect(pixels).not.toEqual([0, 0, 0, 0]); + + var attributes = primitive.getGeometryInstanceAttributes('extent1'); + expect(attributes.color).toBeDefined(); + attributes.color = [255, 255, 255, 255]; + + ClearCommand.ALL.execute(context); + expect(context.readPixels()).toEqual([0, 0, 0, 0]); + + render(context, frameState, primitive); + var newPixels = context.readPixels(); + expect(newPixels).not.toEqual([0, 0, 0, 0]); + expect(newPixels).not.toEqual(pixels); + + primitive = primitive && primitive.destroy(); + }); + + it('modify show instance attribute', function() { + var primitive = new Primitive({ + geometryInstances : extentInstance1, + appearance : new PerInstanceColorAppearance(), + allowColumbusView : false + }); + + frameState.camera.controller.viewExtent(extent1); + us.update(frameState); + + ClearCommand.ALL.execute(context); + expect(context.readPixels()).toEqual([0, 0, 0, 0]); + + render(context, frameState, primitive); + expect(context.readPixels()).not.toEqual([0, 0, 0, 0]); + + var attributes = primitive.getGeometryInstanceAttributes('extent1'); + expect(attributes.show).toBeDefined(); + attributes.show = [0]; + + ClearCommand.ALL.execute(context); + expect(context.readPixels()).toEqual([0, 0, 0, 0]); + + render(context, frameState, primitive); + expect(context.readPixels()).toEqual([0, 0, 0, 0]); + + primitive = primitive && primitive.destroy(); + }); + + it('picking', function() { + var primitive = new Primitive({ + geometryInstances : [extentInstance1, extentInstance2], + appearance : new PerInstanceColorAppearance(), + allowColumbusView : false + }); + + frameState.camera.controller.viewExtent(extent1); + us.update(frameState); + + expect(pick(context, frameState, primitive)).toEqual('extent1'); + + frameState.camera.controller.viewExtent(extent2); + us.update(frameState); + + expect(pick(context, frameState, primitive)).toEqual('extent2'); + + primitive = primitive && primitive.destroy(); + }); + + it('update throws when geometry primitive types are different', function() { + var primitive = new Primitive({ + geometryInstances : [ + new GeometryInstance({ + geometry : new Geometry({ + attributes : { + position : new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : new Float32Array([1.0, 2.0, 3.0, 4.0]) + }) + }, + primitiveType : PrimitiveType.LINES + }) + }), + new GeometryInstance({ + geometry : new Geometry({ + attributes : { + position : new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : new Float32Array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0]) + }) + }, + primitiveType : PrimitiveType.TRIANGLES + }) + }) + ], + appearance : new PerInstanceColorAppearance() + }); + + expect(function() { + primitive.update(context, frameState, []); + }).toThrow(); + }); + + it('shader validation', function() { + var primitive = new Primitive({ + geometryInstances : [extentInstance1, extentInstance2], + allowColumbusView : false, + appearance : new MaterialAppearance({ + materialSupport : MaterialAppearance.MaterialSupport.ALL + }) + }); + + expect(function() { + primitive.update(context, frameState, []); + }).toThrow(); + }); + + it('setting per instance attribute throws when value is undefined', function() { + var primitive = new Primitive({ + geometryInstances : extentInstance1, + appearance : new PerInstanceColorAppearance(), + allowColumbusView : false + }); + + primitive.update(context, frameState, []); + var attributes = primitive.getGeometryInstanceAttributes('extent1'); + + expect(function() { + attributes.color = undefined; + }).toThrow(); + + primitive = primitive && primitive.destroy(); + }); + + it('getGeometryInstanceAttributes throws without id', function() { + var primitive = new Primitive({ + geometryInstances : extentInstance1, + appearance : new PerInstanceColorAppearance(), + allowColumbusView : false + }); + + primitive.update(context, frameState, []); + + expect(function() { + primitive.getGeometryInstanceAttributes(); + }).toThrow(); + + primitive = primitive && primitive.destroy(); + }); + + it('getGeometryInstanceAttributes caches results', function() { + var primitive = new Primitive({ + geometryInstances : extentInstance1, + appearance : new PerInstanceColorAppearance(), + allowColumbusView : false + }); + + primitive.update(context, frameState, []); + + var attributes1 = primitive.getGeometryInstanceAttributes('extent1'); + var attributes2 = primitive.getGeometryInstanceAttributes('extent1'); + expect(attributes1).toBe(attributes2); + + primitive = primitive && primitive.destroy(); + }); + + it('getGeometryInstanceAttributes throws if update was not called', function() { + var primitive = new Primitive({ + geometryInstances : extentInstance1, + appearance : new PerInstanceColorAppearance(), + allowColumbusView : false + }); + + expect(function() { + primitive.getGeometryInstanceAttributes('extent1'); + }).toThrow(); + + primitive = primitive && primitive.destroy(); + }); + + it('getGeometryInstanceAttributes returns undefined if id does not exist', function() { + var primitive = new Primitive({ + geometryInstances : extentInstance1, + appearance : new PerInstanceColorAppearance(), + allowColumbusView : false + }); + + primitive.update(context, frameState, []); + + expect(primitive.getGeometryInstanceAttributes('unknown')).not.toBeDefined(); + + primitive = primitive && primitive.destroy(); + }); + + it('isDestroyed', function() { + var p = new Primitive(); + expect(p.isDestroyed()).toEqual(false); + p.destroy(); + expect(p.isDestroyed()).toEqual(true); + }); + +}); diff --git a/Specs/Scene/createTangentSpaceDebugPrimitiveSpec.js b/Specs/Scene/createTangentSpaceDebugPrimitiveSpec.js new file mode 100644 index 000000000000..c54a1e82e833 --- /dev/null +++ b/Specs/Scene/createTangentSpaceDebugPrimitiveSpec.js @@ -0,0 +1,63 @@ +/*global defineSuite*/ +defineSuite([ + 'Scene/createTangentSpaceDebugPrimitive', + 'Core/EllipsoidGeometry', + 'Core/Cartesian3', + 'Core/Ellipsoid', + 'Core/Matrix4', + 'Core/VertexFormat', + 'Core/PrimitiveType' + ], function( + createTangentSpaceDebugPrimitive, + EllipsoidGeometry, + Cartesian3, + Ellipsoid, + Matrix4, + VertexFormat, + PrimitiveType) { + "use strict"; + /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/ + + + it('computes all attributes', function() { + var geometry = new EllipsoidGeometry({ + vertexFormat : VertexFormat.ALL, + ellipsoid : new Ellipsoid(500000.0, 500000.0, 1000000.0) + }); + var modelMatrix = Matrix4.multiplyByTranslation(Matrix4.IDENTITY, new Cartesian3(0.0, 0.0, 11000000.0)); + + var primitive = createTangentSpaceDebugPrimitive({ + geometry : geometry, + modelMatrix : modelMatrix, + length : 1000.0 + }); + + expect(primitive.geometryInstances).toBeDefined(); + expect(primitive.appearance).toBeDefined(); + + var instances = primitive.geometryInstances; + expect(instances.length).toEqual(3); + + expect(instances[0].modelMatrix).toEqual(modelMatrix); + expect(instances[1].modelMatrix).toEqual(modelMatrix); + expect(instances[2].modelMatrix).toEqual(modelMatrix); + + expect(instances[0].attributes).toBeDefined(); + expect(instances[0].attributes.color).toBeDefined(); + expect(instances[1].attributes).toBeDefined(); + expect(instances[1].attributes.color).toBeDefined(); + expect(instances[2].attributes).toBeDefined(); + expect(instances[2].attributes.color).toBeDefined(); + + expect(instances[0].geometry.primitiveType).toEqual(PrimitiveType.LINES); + expect(instances[1].geometry.primitiveType).toEqual(PrimitiveType.LINES); + expect(instances[2].geometry.primitiveType).toEqual(PrimitiveType.LINES); + }); + + it('throws without geometry', function() { + expect(function() { + createTangentSpaceDebugPrimitive(); + }).toThrow(); + }); + +}); From 62e4ffa484f345492032e5f9a7c4cd8be4c5c1da Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Tue, 2 Jul 2013 21:36:59 -0400 Subject: [PATCH 287/306] Add render tests for Primitive in 2D and Columbus view. --- Source/Scene/CameraController.js | 10 ++++++---- Specs/Scene/PrimitiveSpec.js | 4 ++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Source/Scene/CameraController.js b/Source/Scene/CameraController.js index 3735a4437aec..e212a597387d 100644 --- a/Source/Scene/CameraController.js +++ b/Source/Scene/CameraController.js @@ -890,8 +890,8 @@ define([ if (!positionOnly) { var direction = Cartesian3.clone(Cartesian3.UNIT_Z, camera.direction); Cartesian3.negate(direction, direction); - var right = Cartesian3.clone(Cartesian3.UNIT_X, camera.right); - Cartesian3.cross(right, direction, camera.up); + Cartesian3.clone(Cartesian3.UNIT_X, camera.right); + Cartesian3.clone(Cartesian3.UNIT_Y, camera.up); } return result; @@ -947,8 +947,10 @@ define([ frustum.top = top; frustum.bottom = -top; - var cameraRight = Cartesian3.clone(Cartesian3.UNIT_X, camera.right); - Cartesian3.cross(cameraRight, camera.direction, camera.up); + var direction = Cartesian3.clone(Cartesian3.UNIT_Z, camera.direction); + Cartesian3.negate(direction, direction); + Cartesian3.clone(Cartesian3.UNIT_X, camera.right); + Cartesian3.clone(Cartesian3.UNIT_Y, camera.up); } return result; diff --git a/Specs/Scene/PrimitiveSpec.js b/Specs/Scene/PrimitiveSpec.js index c295760a6c81..7f0cb034efd7 100644 --- a/Specs/Scene/PrimitiveSpec.js +++ b/Specs/Scene/PrimitiveSpec.js @@ -228,7 +228,6 @@ defineSuite([ primitive = primitive && primitive.destroy(); }); - /* it('renders in Columbus view when allowColumbusView is true', function() { var primitive = new Primitive({ geometryInstances : [extentInstance1, extentInstance2], @@ -237,6 +236,7 @@ defineSuite([ }); frameState.mode = SceneMode.COLUMBUS_VIEW; + frameState.morphTime = frameState.mode.morphTime; frameState.camera.transform = new Matrix4(0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, @@ -273,6 +273,7 @@ defineSuite([ }); frameState.mode = SceneMode.SCENE2D; + frameState.morphTime = frameState.mode.morphTime; frameState.camera.transform = new Matrix4(0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, @@ -306,7 +307,6 @@ defineSuite([ frameState = createFrameState(); // reset frame state primitive = primitive && primitive.destroy(); }); - */ it('transforms to world coordinates', function() { var primitive = new Primitive({ From 9258f922913cd78d412ef8fdddc7b2f710c8d903 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Wed, 3 Jul 2013 15:21:42 -0400 Subject: [PATCH 288/306] Add rendering tests for box, circle, and ellipse geometry. Fix ellipse bounding sphere when at a height above the ellipsoid. --- Source/Core/EllipseGeometry.js | 5 +- Specs/Scene/GeometryRenderingSpec.js | 381 +++++++++++++++++++++++++++ Specs/Scene/PrimitiveSpec.js | 4 +- 3 files changed, 386 insertions(+), 4 deletions(-) create mode 100644 Specs/Scene/GeometryRenderingSpec.js diff --git a/Source/Core/EllipseGeometry.js b/Source/Core/EllipseGeometry.js index 345a8dcc17f0..315e211ce56d 100644 --- a/Source/Core/EllipseGeometry.js +++ b/Source/Core/EllipseGeometry.js @@ -423,6 +423,9 @@ define([ indices[indicesIndex++] = positionIndex++; } + var boundingSphereCenter = Cartesian3.multiplyByScalar(ellipsoid.geodeticSurfaceNormal(center), height); + Cartesian3.add(center, boundingSphereCenter, boundingSphereCenter); + /** * An object containing {@link GeometryAttribute} properties named after each of the * true values of the {@link VertexFormat} option. @@ -452,7 +455,7 @@ define([ * * @type BoundingSphere */ - this.boundingSphere = new BoundingSphere(center, semiMajorAxis); + this.boundingSphere = new BoundingSphere(boundingSphereCenter, semiMajorAxis); }; return EllipseGeometry; diff --git a/Specs/Scene/GeometryRenderingSpec.js b/Specs/Scene/GeometryRenderingSpec.js new file mode 100644 index 000000000000..92737dc1da21 --- /dev/null +++ b/Specs/Scene/GeometryRenderingSpec.js @@ -0,0 +1,381 @@ +/*global defineSuite*/ +defineSuite([ + 'Core/BoxGeometry', + 'Core/CircleGeometry', + 'Core/EllipseGeometry', + 'Core/ExtentGeometry', + 'Core/defaultValue', + 'Core/Geometry', + 'Core/GeometryAttribute', + 'Core/GeometryInstance', + 'Core/ColorGeometryInstanceAttribute', + 'Core/GeometryInstanceAttribute', + 'Core/ComponentDatatype', + 'Core/Cartesian3', + 'Core/Matrix4', + 'Core/Extent', + 'Core/Ellipsoid', + 'Core/PrimitiveType', + 'Core/Transforms', + 'Core/Cartographic', + 'Core/BoundingSphere', + 'Core/Math', + 'Renderer/ClearCommand', + 'Scene/PerInstanceColorAppearance', + 'Scene/Primitive', + 'Scene/SceneMode', + 'Scene/OrthographicFrustum', + 'Specs/render', + 'Specs/pick', + 'Specs/createCanvas', + 'Specs/destroyCanvas', + 'Specs/createContext', + 'Specs/destroyContext', + 'Specs/createFrameState' + ], 'Scene/GeometryRendering', function( + BoxGeometry, + CircleGeometry, + EllipseGeometry, + ExtentGeometry, + defaultValue, + Geometry, + GeometryAttribute, + GeometryInstance, + ColorGeometryInstanceAttribute, + GeometryInstanceAttribute, + ComponentDatatype, + Cartesian3, + Matrix4, + Extent, + Ellipsoid, + PrimitiveType, + Transforms, + Cartographic, + BoundingSphere, + CesiumMath, + ClearCommand, + PerInstanceColorAppearance, + Primitive, + SceneMode, + OrthographicFrustum, + render, + pick, + createCanvas, + destroyCanvas, + createContext, + destroyContext, + createFrameState) { + "use strict"; + /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/ + + var context; + var ellipsoid; + + beforeAll(function() { + context = createContext(); + ellipsoid = Ellipsoid.WGS84; + }); + + afterAll(function() { + destroyContext(context); + }); + + function viewSphere3D(camera, sphere, modelMatrix) { + sphere = BoundingSphere.transform(sphere, modelMatrix); + var center = sphere.center.clone(); + var radius = sphere.radius; + + var direction = ellipsoid.geodeticSurfaceNormal(center, camera.direction); + Cartesian3.negate(direction, direction); + Cartesian3.normalize(direction, direction); + var right = Cartesian3.cross(direction, Cartesian3.UNIT_Z, camera.right); + Cartesian3.normalize(right, right); + Cartesian3.cross(right, direction, camera.up); + + var scalar = center.magnitude() + radius; + Cartesian3.normalize(center, center); + Cartesian3.multiplyByScalar(center, scalar, camera.position); + } + + function render3D(instance, boundingSphere) { + var primitive = new Primitive({ + geometryInstances : instance, + appearance : new PerInstanceColorAppearance() + }); + + var frameState = createFrameState(); + + var sphere = defaultValue(instance.geometry.boundingSphere, boundingSphere); + var modelMatrix = defaultValue(instance.modelMatrix, Matrix4.IDENTITY); + viewSphere3D(frameState.camera, sphere, modelMatrix); + context.getUniformState().update(frameState); + + ClearCommand.ALL.execute(context); + expect(context.readPixels()).toEqual([0, 0, 0, 0]); + + render(context, frameState, primitive); + expect(context.readPixels()).not.toEqual([0, 0, 0, 0]); + + primitive = primitive && primitive.destroy(); + } + + function viewSphereCV(camera, sphere, modelMatrix) { + sphere = BoundingSphere.transform(sphere, modelMatrix); + sphere = BoundingSphere.projectTo2D(sphere); + var center = sphere.center.clone(); + var radius = sphere.radius; + + Cartesian3.clone(Cartesian3.UNIT_Z, camera.direction); + Cartesian3.negate(camera.direction, camera.direction); + Cartesian3.clone(Cartesian3.UNIT_Y, camera.up); + Cartesian3.clone(Cartesian3.UNIT_X, camera.right); + + camera.position.x = center.y; + camera.position.y = center.z; + camera.position.z = center.x + radius; + } + + function renderCV(instance, boundingSphere) { + var primitive = new Primitive({ + geometryInstances : instance, + appearance : new PerInstanceColorAppearance() + }); + + var frameState = createFrameState(); + frameState.mode = SceneMode.COLUMBUS_VIEW; + frameState.morphTime = frameState.mode.morphTime; + frameState.camera.transform = new Matrix4(0.0, 0.0, 1.0, 0.0, + 1.0, 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 1.0); + frameState.camera.controller.update(frameState.mode, frameState.scene2D); + + var sphere = defaultValue(instance.geometry.boundingSphere, boundingSphere); + var modelMatrix = defaultValue(instance.modelMatrix, Matrix4.IDENTITY); + viewSphereCV(frameState.camera, sphere, modelMatrix); + context.getUniformState().update(frameState); + + ClearCommand.ALL.execute(context); + expect(context.readPixels()).toEqual([0, 0, 0, 0]); + + render(context, frameState, primitive); + expect(context.readPixels()).not.toEqual([0, 0, 0, 0]); + + primitive = primitive && primitive.destroy(); + } + + function viewSphere2D(camera, sphere, modelMatrix) { + sphere = BoundingSphere.transform(sphere, modelMatrix); + sphere = BoundingSphere.projectTo2D(sphere); + var center = sphere.center.clone(); + var radius = sphere.radius; + + Cartesian3.clone(Cartesian3.UNIT_Z, camera.direction); + Cartesian3.negate(camera.direction, camera.direction); + Cartesian3.clone(Cartesian3.UNIT_Y, camera.up); + Cartesian3.clone(Cartesian3.UNIT_X, camera.right); + + camera.position.x = center.y; + camera.position.y = center.z; + + var frustum = camera.frustum; + var ratio = camera.frustum.right / camera.frustum.top; + frustum.right = radius * 0.25; + frustum.top = frustum.right / ratio; + frustum.left = -frustum.right; + frustum.bottom = -frustum.top; + } + + function render2D(instance, boundingSphere) { + var primitive = new Primitive({ + geometryInstances : instance, + appearance : new PerInstanceColorAppearance() + }); + + var frameState = createFrameState(); + frameState.mode = SceneMode.SCENE2D; + frameState.morphTime = frameState.mode.morphTime; + frameState.camera.transform = new Matrix4(0.0, 0.0, 1.0, 0.0, + 1.0, 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 1.0); + var frustum = new OrthographicFrustum(); + frustum.right = ellipsoid.getMaximumRadius() * Math.PI; + frustum.left = -frustum.right; + frustum.top = frustum.right; + frustum.bottom = -frustum.top; + frameState.camera.frustum = frustum; + frameState.camera.controller.update(frameState.mode, frameState.scene2D); + + var sphere = defaultValue(instance.geometry.boundingSphere, boundingSphere); + var modelMatrix = defaultValue(instance.modelMatrix, Matrix4.IDENTITY); + viewSphere2D(frameState.camera, sphere, modelMatrix); + context.getUniformState().update(frameState); + + ClearCommand.ALL.execute(context); + expect(context.readPixels()).toEqual([0, 0, 0, 0]); + + render(context, frameState, primitive); + expect(context.readPixels()).not.toEqual([0, 0, 0, 0]); + + primitive = primitive && primitive.destroy(); + } + + function pickGeometry(instance, boundingSphere) { + var primitive = new Primitive({ + geometryInstances : instance, + appearance : new PerInstanceColorAppearance() + }); + + var frameState = createFrameState(); + + var sphere = defaultValue(instance.geometry.boundingSphere, boundingSphere); + var modelMatrix = defaultValue(instance.modelMatrix, Matrix4.IDENTITY); + viewSphere3D(frameState.camera, sphere, modelMatrix); + context.getUniformState().update(frameState); + + expect(pick(context, frameState, primitive)).toEqual(instance.id); + + primitive = primitive && primitive.destroy(); + } + + describe('BoxGeometry', function() { + var instance; + beforeAll(function() { + instance = new GeometryInstance({ + geometry : new BoxGeometry({ + vertexFormat : PerInstanceColorAppearance.VERTEX_FORMAT, + dimensions : new Cartesian3(1000000.0, 1000000.0, 2000000.0) + }), + modelMatrix : Matrix4.multiplyByTranslation(Transforms.eastNorthUpToFixedFrame( + ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-75.59777, 40.03883))), new Cartesian3(0.0, 0.0, 3000000.0)), + id : 'box', + attributes : { + color : new ColorGeometryInstanceAttribute(1.0, 1.0, 0.0, 1.0) + } + }); + }); + + it('3D', function() { + render3D(instance); + }); + + it('Columbus view', function() { + renderCV(instance); + }); + + it('2D', function() { + render2D(instance); + }); + + it('pick', function() { + pickGeometry(instance); + }); + }, 'WebGL'); + + describe('CircleGeometry', function() { + var instance; + beforeAll(function() { + instance = new GeometryInstance({ + geometry : new CircleGeometry({ + vertexFormat : PerInstanceColorAppearance.VERTEX_FORMAT, + ellipsoid : ellipsoid, + center : ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-100, 20)), + radius : 1000000.0 + }), + id : 'circle', + attributes : { + color : new ColorGeometryInstanceAttribute(1.0, 1.0, 0.0, 1.0) + } + }); + }); + + it('3D', function() { + render3D(instance); + }); + + it('Columbus view', function() { + renderCV(instance); + }); + + it('2D', function() { + render2D(instance); + }); + + it('pick', function() { + pickGeometry(instance); + }); + }, 'WebGL'); + + describe('EllipseGeometry', function() { + var instance; + beforeAll(function() { + instance = new GeometryInstance({ + geometry : new EllipseGeometry({ + vertexFormat : PerInstanceColorAppearance.VERTEX_FORMAT, + ellipsoid : ellipsoid, + center : ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-100, 20)), + semiMinorAxis : 1000000.0, + semiMajorAxis : 1000000.0 + }), + id : 'ellipse', + attributes : { + color : new ColorGeometryInstanceAttribute(1.0, 1.0, 0.0, 1.0) + } + }); + }); + + it('3D', function() { + render3D(instance); + }); + + it('Columbus view', function() { + renderCV(instance); + }); + + it('2D', function() { + render2D(instance); + }); + + it('pick', function() { + pickGeometry(instance); + }); + + it('rotated', function() { + var rotated = new GeometryInstance({ + geometry : new EllipseGeometry({ + vertexFormat : PerInstanceColorAppearance.VERTEX_FORMAT, + ellipsoid : ellipsoid, + center : ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-100, 20)), + semiMinorAxis : 1000000.0, + semiMajorAxis : 1000000.0, + bearing : CesiumMath.PI_OVER_FOUR + }), + id : 'ellipse', + attributes : { + color : new ColorGeometryInstanceAttribute(1.0, 1.0, 0.0, 1.0) + } + }); + render3D(rotated); + }); + + it('at height', function() { + var atHeight = new GeometryInstance({ + geometry : new EllipseGeometry({ + vertexFormat : PerInstanceColorAppearance.VERTEX_FORMAT, + ellipsoid : ellipsoid, + center : ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-100, 20)), + semiMinorAxis : 1000000.0, + semiMajorAxis : 1000000.0, + height : 1000000.0 + }), + id : 'ellipse', + attributes : { + color : new ColorGeometryInstanceAttribute(1.0, 1.0, 0.0, 1.0) + } + }); + render3D(atHeight); + }); + }, 'WebGL'); + +}); diff --git a/Specs/Scene/PrimitiveSpec.js b/Specs/Scene/PrimitiveSpec.js index 7f0cb034efd7..a6189e7b523d 100644 --- a/Specs/Scene/PrimitiveSpec.js +++ b/Specs/Scene/PrimitiveSpec.js @@ -19,7 +19,6 @@ defineSuite([ 'Scene/PerInstanceColorAppearance', 'Scene/SceneMode', 'Scene/OrthographicFrustum', - 'Scene/Camera', 'Specs/render', 'Specs/pick', 'Specs/createCanvas', @@ -47,7 +46,6 @@ defineSuite([ PerInstanceColorAppearance, SceneMode, OrthographicFrustum, - Camera, render, pick, createCanvas, @@ -72,7 +70,7 @@ defineSuite([ beforeAll(function() { context = createContext(); - frameState = createFrameState(new Camera(context.getCanvas())); + frameState = createFrameState(); us = context.getUniformState(); us.update(frameState); From 565b64cfdeedfec75a001203cb3fabc3cb16f5a3 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Wed, 3 Jul 2013 18:35:40 -0400 Subject: [PATCH 289/306] Add ellipsoid, extent, and polygon rendering tests. Fix polygon bounding sphere at a height above the ellipsoid. --- Source/Core/PolygonGeometry.js | 11 +- Specs/Scene/GeometryRenderingSpec.js | 215 +++++++++++++++++++++++++-- 2 files changed, 214 insertions(+), 12 deletions(-) diff --git a/Source/Core/PolygonGeometry.js b/Source/Core/PolygonGeometry.js index 7111becf2571..0f59f3f83d2a 100644 --- a/Source/Core/PolygonGeometry.js +++ b/Source/Core/PolygonGeometry.js @@ -85,7 +85,7 @@ define([ var createGeometryFromPositionsPositions = []; - function createGeometryFromPositions(ellipsoid, positions, boundingSphere, granularity) { + function createGeometryFromPositions(ellipsoid, positions, granularity) { var cleanedPositions = PolygonPipeline.removeDuplicates(positions); if (cleanedPositions.length < 3) { throw new DeveloperError('Duplicate positions result in not enough positions to form a polygon.'); @@ -209,7 +209,7 @@ define([ outerPositions = positions; boundingSphere = BoundingSphere.fromPoints(positions); - geometry = createGeometryFromPositions(ellipsoid, positions, boundingSphere, granularity); + geometry = createGeometryFromPositions(ellipsoid, positions, granularity); if (typeof geometry !== 'undefined') { geometries.push(geometry); } @@ -262,7 +262,7 @@ define([ boundingSphere = BoundingSphere.fromPoints(outerPositions); for (i = 0; i < polygonHierarchy.length; i++) { - geometry = createGeometryFromPositions(ellipsoid, polygonHierarchy[i], boundingSphere, granularity); + geometry = createGeometryFromPositions(ellipsoid, polygonHierarchy[i], granularity); if (typeof geometry !== 'undefined') { geometries.push(geometry); } @@ -274,6 +274,11 @@ define([ geometry = GeometryPipeline.combine(geometries); geometry = PolygonPipeline.scaleToGeodeticHeight(geometry, height, ellipsoid); + var center = boundingSphere.center; + var mag = center.magnitude(); + ellipsoid.geodeticSurfaceNormal(center, center); + Cartesian3.multiplyByScalar(center, mag + height, center); + var attributes = {}; if (vertexFormat.position) { diff --git a/Specs/Scene/GeometryRenderingSpec.js b/Specs/Scene/GeometryRenderingSpec.js index 92737dc1da21..bb56ccd7deb8 100644 --- a/Specs/Scene/GeometryRenderingSpec.js +++ b/Specs/Scene/GeometryRenderingSpec.js @@ -3,7 +3,9 @@ defineSuite([ 'Core/BoxGeometry', 'Core/CircleGeometry', 'Core/EllipseGeometry', + 'Core/EllipsoidGeometry', 'Core/ExtentGeometry', + 'Core/PolygonGeometry', 'Core/defaultValue', 'Core/Geometry', 'Core/GeometryAttribute', @@ -36,7 +38,9 @@ defineSuite([ BoxGeometry, CircleGeometry, EllipseGeometry, + EllipsoidGeometry, ExtentGeometry, + PolygonGeometry, defaultValue, Geometry, GeometryAttribute, @@ -106,8 +110,7 @@ defineSuite([ var frameState = createFrameState(); var sphere = defaultValue(instance.geometry.boundingSphere, boundingSphere); - var modelMatrix = defaultValue(instance.modelMatrix, Matrix4.IDENTITY); - viewSphere3D(frameState.camera, sphere, modelMatrix); + viewSphere3D(frameState.camera, sphere, instance.modelMatrix); context.getUniformState().update(frameState); ClearCommand.ALL.execute(context); @@ -123,7 +126,7 @@ defineSuite([ sphere = BoundingSphere.transform(sphere, modelMatrix); sphere = BoundingSphere.projectTo2D(sphere); var center = sphere.center.clone(); - var radius = sphere.radius; + var radius = sphere.radius * 0.5; Cartesian3.clone(Cartesian3.UNIT_Z, camera.direction); Cartesian3.negate(camera.direction, camera.direction); @@ -151,8 +154,7 @@ defineSuite([ frameState.camera.controller.update(frameState.mode, frameState.scene2D); var sphere = defaultValue(instance.geometry.boundingSphere, boundingSphere); - var modelMatrix = defaultValue(instance.modelMatrix, Matrix4.IDENTITY); - viewSphereCV(frameState.camera, sphere, modelMatrix); + viewSphereCV(frameState.camera, sphere, instance.modelMatrix); context.getUniformState().update(frameState); ClearCommand.ALL.execute(context); @@ -208,8 +210,7 @@ defineSuite([ frameState.camera.controller.update(frameState.mode, frameState.scene2D); var sphere = defaultValue(instance.geometry.boundingSphere, boundingSphere); - var modelMatrix = defaultValue(instance.modelMatrix, Matrix4.IDENTITY); - viewSphere2D(frameState.camera, sphere, modelMatrix); + viewSphere2D(frameState.camera, sphere, instance.modelMatrix); context.getUniformState().update(frameState); ClearCommand.ALL.execute(context); @@ -230,8 +231,7 @@ defineSuite([ var frameState = createFrameState(); var sphere = defaultValue(instance.geometry.boundingSphere, boundingSphere); - var modelMatrix = defaultValue(instance.modelMatrix, Matrix4.IDENTITY); - viewSphere3D(frameState.camera, sphere, modelMatrix); + viewSphere3D(frameState.camera, sphere, instance.modelMatrix); context.getUniformState().update(frameState); expect(pick(context, frameState, primitive)).toEqual(instance.id); @@ -378,4 +378,201 @@ defineSuite([ }); }, 'WebGL'); + describe('EllipsoidGeometry', function() { + var instance; + beforeAll(function() { + instance = new GeometryInstance({ + geometry : new EllipsoidGeometry({ + vertexFormat : PerInstanceColorAppearance.VERTEX_FORMAT, + ellipsoid : new Ellipsoid(1000000.0, 1000000.0, 500000.0) + }), + modelMatrix : Matrix4.multiplyByTranslation(Transforms.eastNorthUpToFixedFrame( + ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-100, 20))), new Cartesian3(0.0, 0.0, 1000000.0)), + id : 'ellipsoid', + attributes : { + color : new ColorGeometryInstanceAttribute(1.0, 1.0, 0.0, 1.0) + } + }); + }); + + it('3D', function() { + render3D(instance); + }); + + it('Columbus view', function() { + renderCV(instance); + }); + + it('2D', function() { + render2D(instance); + }); + + it('pick', function() { + pickGeometry(instance); + }); + }, 'WebGL'); + + describe('ExtentGeometry', function() { + var instance; + var extent; + beforeAll(function() { + extent = Extent.fromDegrees(0, 0, 1, 1); + instance = new GeometryInstance({ + geometry : new ExtentGeometry({ + vertexFormat : PerInstanceColorAppearance.VERTEX_FORMAT, + ellipsoid : ellipsoid, + extent : extent + }), + id : 'extent', + attributes : { + color : new ColorGeometryInstanceAttribute(1.0, 1.0, 0.0, 1.0) + } + }); + }); + + it('3D', function() { + render3D(instance); + }); + + it('Columbus view', function() { + renderCV(instance); + }); + + it('2D', function() { + render2D(instance); + }); + + it('pick', function() { + pickGeometry(instance); + }); + + it('rotated', function() { + var rotated = new GeometryInstance({ + geometry : new ExtentGeometry({ + vertexFormat : PerInstanceColorAppearance.VERTEX_FORMAT, + ellipsoid : ellipsoid, + extent : extent, + rotation : CesiumMath.PI_OVER_FOUR + }), + id : 'extent', + attributes : { + color : new ColorGeometryInstanceAttribute(1.0, 1.0, 0.0, 1.0) + } + }); + render3D(rotated); + }); + + it('at height', function() { + var atHeight = new GeometryInstance({ + geometry : new ExtentGeometry({ + vertexFormat : PerInstanceColorAppearance.VERTEX_FORMAT, + ellipsoid : ellipsoid, + extent : extent, + height : 100000.0 + }), + id : 'extent', + attributes : { + color : new ColorGeometryInstanceAttribute(1.0, 1.0, 0.0, 1.0) + } + }); + render3D(atHeight); + }); + }, 'WebGL'); + + describe('PolygonGeometry', function() { + var instance; + beforeAll(function() { + instance = new GeometryInstance({ + geometry : new PolygonGeometry({ + vertexFormat : PerInstanceColorAppearance.VERTEX_FORMAT, + ellipsoid : ellipsoid, + positions : ellipsoid.cartographicArrayToCartesianArray([ + Cartographic.fromDegrees(0.0, 45.0), + Cartographic.fromDegrees(10.0, 45.0), + Cartographic.fromDegrees(10.0, 55.0), + Cartographic.fromDegrees(0.0, 55.0) + ]) + }), + id : 'polygon', + attributes : { + color : new ColorGeometryInstanceAttribute(1.0, 1.0, 0.0, 1.0) + } + }); + }); + + it('3D', function() { + render3D(instance); + }); + + it('Columbus view', function() { + renderCV(instance); + }); + + it('2D', function() { + render2D(instance); + }); + + it('pick', function() { + pickGeometry(instance); + }); + + it('at height', function() { + var atHeight = new GeometryInstance({ + geometry : new PolygonGeometry({ + vertexFormat : PerInstanceColorAppearance.VERTEX_FORMAT, + ellipsoid : ellipsoid, + positions : ellipsoid.cartographicArrayToCartesianArray([ + Cartographic.fromDegrees(0.0, 45.0), + Cartographic.fromDegrees(10.0, 45.0), + Cartographic.fromDegrees(10.0, 55.0), + Cartographic.fromDegrees(0.0, 55.0) + ]), + height : 3000000.0 + }), + id : 'polygon', + attributes : { + color : new ColorGeometryInstanceAttribute(1.0, 1.0, 0.0, 1.0) + } + }); + render3D(atHeight); + }); + + it('hierarchy', function() { + var hierarchy = new GeometryInstance({ + geometry : new PolygonGeometry({ + vertexFormat : PerInstanceColorAppearance.VERTEX_FORMAT, + polygonHierarchy : { + positions : ellipsoid.cartographicArrayToCartesianArray([ + Cartographic.fromDegrees(-109.0, 30.0), + Cartographic.fromDegrees(-95.0, 30.0), + Cartographic.fromDegrees(-95.0, 40.0), + Cartographic.fromDegrees(-109.0, 40.0) + ]), + holes : [{ + positions : ellipsoid.cartographicArrayToCartesianArray([ + Cartographic.fromDegrees(-107.0, 31.0), + Cartographic.fromDegrees(-107.0, 39.0), + Cartographic.fromDegrees(-97.0, 39.0), + Cartographic.fromDegrees(-97.0, 31.0) + ]), + holes : [{ + positions : ellipsoid.cartographicArrayToCartesianArray([ + Cartographic.fromDegrees(-106.5, 31.5), + Cartographic.fromDegrees(-97.5, 31.5), + Cartographic.fromDegrees(-97.5, 38.5), + Cartographic.fromDegrees(-106.5, 38.5) + ]) + }] + }] + } + }), + id : 'polygon', + attributes : { + color : new ColorGeometryInstanceAttribute(1.0, 1.0, 0.0, 1.0) + } + }); + render3D(hierarchy); + }); + }, 'WebGL'); + }); From 570d60a493863b38b356841bdadf1e40c61252ec Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 8 Jul 2013 15:32:31 -0400 Subject: [PATCH 290/306] Add wall geometry rendering test. --- Specs/Scene/GeometryRenderingSpec.js | 75 ++++++++++++++++++++++++++-- 1 file changed, 72 insertions(+), 3 deletions(-) diff --git a/Specs/Scene/GeometryRenderingSpec.js b/Specs/Scene/GeometryRenderingSpec.js index bb56ccd7deb8..fd97ea7331c3 100644 --- a/Specs/Scene/GeometryRenderingSpec.js +++ b/Specs/Scene/GeometryRenderingSpec.js @@ -6,6 +6,7 @@ defineSuite([ 'Core/EllipsoidGeometry', 'Core/ExtentGeometry', 'Core/PolygonGeometry', + 'Core/WallGeometry', 'Core/defaultValue', 'Core/Geometry', 'Core/GeometryAttribute', @@ -41,6 +42,7 @@ defineSuite([ EllipsoidGeometry, ExtentGeometry, PolygonGeometry, + WallGeometry, defaultValue, Geometry, GeometryAttribute, @@ -101,7 +103,7 @@ defineSuite([ Cartesian3.multiplyByScalar(center, scalar, camera.position); } - function render3D(instance, boundingSphere) { + function render3D(instance, afterView, boundingSphere) { var primitive = new Primitive({ geometryInstances : instance, appearance : new PerInstanceColorAppearance() @@ -111,6 +113,11 @@ defineSuite([ var sphere = defaultValue(instance.geometry.boundingSphere, boundingSphere); viewSphere3D(frameState.camera, sphere, instance.modelMatrix); + + if (typeof afterView === 'function') { + afterView(frameState); + } + context.getUniformState().update(frameState); ClearCommand.ALL.execute(context); @@ -138,7 +145,7 @@ defineSuite([ camera.position.z = center.x + radius; } - function renderCV(instance, boundingSphere) { + function renderCV(instance, afterView, boundingSphere) { var primitive = new Primitive({ geometryInstances : instance, appearance : new PerInstanceColorAppearance() @@ -155,6 +162,11 @@ defineSuite([ var sphere = defaultValue(instance.geometry.boundingSphere, boundingSphere); viewSphereCV(frameState.camera, sphere, instance.modelMatrix); + + if (typeof afterView === 'function') { + afterView(frameState); + } + context.getUniformState().update(frameState); ClearCommand.ALL.execute(context); @@ -222,7 +234,7 @@ defineSuite([ primitive = primitive && primitive.destroy(); } - function pickGeometry(instance, boundingSphere) { + function pickGeometry(instance, afterView, boundingSphere) { var primitive = new Primitive({ geometryInstances : instance, appearance : new PerInstanceColorAppearance() @@ -232,6 +244,11 @@ defineSuite([ var sphere = defaultValue(instance.geometry.boundingSphere, boundingSphere); viewSphere3D(frameState.camera, sphere, instance.modelMatrix); + + if (typeof afterView === 'function') { + afterView(frameState); + } + context.getUniformState().update(frameState); expect(pick(context, frameState, primitive)).toEqual(instance.id); @@ -575,4 +592,56 @@ defineSuite([ }); }, 'WebGL'); + describe('WallGeometry', function() { + var instance; + var afterViewCV; + var afterView3D; + beforeAll(function() { + var height = 100000.0; + + instance = new GeometryInstance({ + geometry : new WallGeometry({ + vertexFormat : PerInstanceColorAppearance.VERTEX_FORMAT, + ellipsoid : ellipsoid, + positions : ellipsoid.cartographicArrayToCartesianArray([ + Cartographic.fromDegrees(0.0, 0.0, height), + Cartographic.fromDegrees(0.01, 0.0, height) + ]) + }), + id : 'wall', + attributes : { + color : new ColorGeometryInstanceAttribute(1.0, 1.0, 0.0, 1.0) + } + }); + + afterView3D = function(frameState) { + var transform = Transforms.eastNorthUpToFixedFrame(instance.geometry.boundingSphere.center); + frameState.camera.controller.rotateDown(-CesiumMath.PI_OVER_TWO, transform); + frameState.camera.controller.zoomIn(instance.geometry.boundingSphere.radius * 0.99); + }; + + afterViewCV = function(frameState) { + var translation = frameState.camera.position.clone(); + translation.z = 0.0; + var transform = Matrix4.fromTranslation(translation); + frameState.camera.controller.rotateDown(-CesiumMath.PI_OVER_TWO, transform); + frameState.camera.controller.zoomIn(instance.geometry.boundingSphere.radius * 1.85); + }; + }); + + it('3D', function() { + render3D(instance, afterView3D); + }); + + it('Columbus view', function() { + renderCV(instance, afterViewCV); + }); + + // walls do not render in 2D + + it('pick', function() { + pickGeometry(instance, afterView3D); + }); + }, 'WebGL'); + }); From aedc2c4f04db8bc87f1806cde7489151c2aba190 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 8 Jul 2013 15:41:07 -0400 Subject: [PATCH 291/306] Add simple polyline geometry rendering tests. --- Specs/Scene/GeometryRenderingSpec.js | 78 ++++++++++++++++++++++------ 1 file changed, 61 insertions(+), 17 deletions(-) diff --git a/Specs/Scene/GeometryRenderingSpec.js b/Specs/Scene/GeometryRenderingSpec.js index fd97ea7331c3..f2b5893240a3 100644 --- a/Specs/Scene/GeometryRenderingSpec.js +++ b/Specs/Scene/GeometryRenderingSpec.js @@ -6,6 +6,7 @@ defineSuite([ 'Core/EllipsoidGeometry', 'Core/ExtentGeometry', 'Core/PolygonGeometry', + 'Core/SimplePolylineGeometry', 'Core/WallGeometry', 'Core/defaultValue', 'Core/Geometry', @@ -42,6 +43,7 @@ defineSuite([ EllipsoidGeometry, ExtentGeometry, PolygonGeometry, + SimplePolylineGeometry, WallGeometry, defaultValue, Geometry, @@ -106,7 +108,9 @@ defineSuite([ function render3D(instance, afterView, boundingSphere) { var primitive = new Primitive({ geometryInstances : instance, - appearance : new PerInstanceColorAppearance() + appearance : new PerInstanceColorAppearance({ + flat : true + }) }); var frameState = createFrameState(); @@ -148,7 +152,9 @@ defineSuite([ function renderCV(instance, afterView, boundingSphere) { var primitive = new Primitive({ geometryInstances : instance, - appearance : new PerInstanceColorAppearance() + appearance : new PerInstanceColorAppearance({ + flat : true + }) }); var frameState = createFrameState(); @@ -203,7 +209,9 @@ defineSuite([ function render2D(instance, boundingSphere) { var primitive = new Primitive({ geometryInstances : instance, - appearance : new PerInstanceColorAppearance() + appearance : new PerInstanceColorAppearance({ + flat : true + }) }); var frameState = createFrameState(); @@ -237,7 +245,9 @@ defineSuite([ function pickGeometry(instance, afterView, boundingSphere) { var primitive = new Primitive({ geometryInstances : instance, - appearance : new PerInstanceColorAppearance() + appearance : new PerInstanceColorAppearance({ + flat : true + }) }); var frameState = createFrameState(); @@ -261,7 +271,7 @@ defineSuite([ beforeAll(function() { instance = new GeometryInstance({ geometry : new BoxGeometry({ - vertexFormat : PerInstanceColorAppearance.VERTEX_FORMAT, + vertexFormat : PerInstanceColorAppearance.FLAT_VERTEX_FORMAT, dimensions : new Cartesian3(1000000.0, 1000000.0, 2000000.0) }), modelMatrix : Matrix4.multiplyByTranslation(Transforms.eastNorthUpToFixedFrame( @@ -295,7 +305,7 @@ defineSuite([ beforeAll(function() { instance = new GeometryInstance({ geometry : new CircleGeometry({ - vertexFormat : PerInstanceColorAppearance.VERTEX_FORMAT, + vertexFormat : PerInstanceColorAppearance.FLAT_VERTEX_FORMAT, ellipsoid : ellipsoid, center : ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-100, 20)), radius : 1000000.0 @@ -329,7 +339,7 @@ defineSuite([ beforeAll(function() { instance = new GeometryInstance({ geometry : new EllipseGeometry({ - vertexFormat : PerInstanceColorAppearance.VERTEX_FORMAT, + vertexFormat : PerInstanceColorAppearance.FLAT_VERTEX_FORMAT, ellipsoid : ellipsoid, center : ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-100, 20)), semiMinorAxis : 1000000.0, @@ -361,7 +371,7 @@ defineSuite([ it('rotated', function() { var rotated = new GeometryInstance({ geometry : new EllipseGeometry({ - vertexFormat : PerInstanceColorAppearance.VERTEX_FORMAT, + vertexFormat : PerInstanceColorAppearance.FLAT_VERTEX_FORMAT, ellipsoid : ellipsoid, center : ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-100, 20)), semiMinorAxis : 1000000.0, @@ -379,7 +389,7 @@ defineSuite([ it('at height', function() { var atHeight = new GeometryInstance({ geometry : new EllipseGeometry({ - vertexFormat : PerInstanceColorAppearance.VERTEX_FORMAT, + vertexFormat : PerInstanceColorAppearance.FLAT_VERTEX_FORMAT, ellipsoid : ellipsoid, center : ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-100, 20)), semiMinorAxis : 1000000.0, @@ -400,7 +410,7 @@ defineSuite([ beforeAll(function() { instance = new GeometryInstance({ geometry : new EllipsoidGeometry({ - vertexFormat : PerInstanceColorAppearance.VERTEX_FORMAT, + vertexFormat : PerInstanceColorAppearance.FLAT_VERTEX_FORMAT, ellipsoid : new Ellipsoid(1000000.0, 1000000.0, 500000.0) }), modelMatrix : Matrix4.multiplyByTranslation(Transforms.eastNorthUpToFixedFrame( @@ -436,7 +446,7 @@ defineSuite([ extent = Extent.fromDegrees(0, 0, 1, 1); instance = new GeometryInstance({ geometry : new ExtentGeometry({ - vertexFormat : PerInstanceColorAppearance.VERTEX_FORMAT, + vertexFormat : PerInstanceColorAppearance.FLAT_VERTEX_FORMAT, ellipsoid : ellipsoid, extent : extent }), @@ -466,7 +476,7 @@ defineSuite([ it('rotated', function() { var rotated = new GeometryInstance({ geometry : new ExtentGeometry({ - vertexFormat : PerInstanceColorAppearance.VERTEX_FORMAT, + vertexFormat : PerInstanceColorAppearance.FLAT_VERTEX_FORMAT, ellipsoid : ellipsoid, extent : extent, rotation : CesiumMath.PI_OVER_FOUR @@ -482,7 +492,7 @@ defineSuite([ it('at height', function() { var atHeight = new GeometryInstance({ geometry : new ExtentGeometry({ - vertexFormat : PerInstanceColorAppearance.VERTEX_FORMAT, + vertexFormat : PerInstanceColorAppearance.FLAT_VERTEX_FORMAT, ellipsoid : ellipsoid, extent : extent, height : 100000.0 @@ -501,7 +511,7 @@ defineSuite([ beforeAll(function() { instance = new GeometryInstance({ geometry : new PolygonGeometry({ - vertexFormat : PerInstanceColorAppearance.VERTEX_FORMAT, + vertexFormat : PerInstanceColorAppearance.FLAT_VERTEX_FORMAT, ellipsoid : ellipsoid, positions : ellipsoid.cartographicArrayToCartesianArray([ Cartographic.fromDegrees(0.0, 45.0), @@ -536,7 +546,7 @@ defineSuite([ it('at height', function() { var atHeight = new GeometryInstance({ geometry : new PolygonGeometry({ - vertexFormat : PerInstanceColorAppearance.VERTEX_FORMAT, + vertexFormat : PerInstanceColorAppearance.FLAT_VERTEX_FORMAT, ellipsoid : ellipsoid, positions : ellipsoid.cartographicArrayToCartesianArray([ Cartographic.fromDegrees(0.0, 45.0), @@ -557,7 +567,7 @@ defineSuite([ it('hierarchy', function() { var hierarchy = new GeometryInstance({ geometry : new PolygonGeometry({ - vertexFormat : PerInstanceColorAppearance.VERTEX_FORMAT, + vertexFormat : PerInstanceColorAppearance.FLAT_VERTEX_FORMAT, polygonHierarchy : { positions : ellipsoid.cartographicArrayToCartesianArray([ Cartographic.fromDegrees(-109.0, 30.0), @@ -601,7 +611,7 @@ defineSuite([ instance = new GeometryInstance({ geometry : new WallGeometry({ - vertexFormat : PerInstanceColorAppearance.VERTEX_FORMAT, + vertexFormat : PerInstanceColorAppearance.FLAT_VERTEX_FORMAT, ellipsoid : ellipsoid, positions : ellipsoid.cartographicArrayToCartesianArray([ Cartographic.fromDegrees(0.0, 0.0, height), @@ -644,4 +654,38 @@ defineSuite([ }); }, 'WebGL'); + describe('SimplePolylineGeometry', function() { + var instance; + beforeAll(function() { + instance = new GeometryInstance({ + geometry : new SimplePolylineGeometry({ + positions : ellipsoid.cartographicArrayToCartesianArray([ + Cartographic.fromDegrees(0.0, 0.0), + Cartographic.fromDegrees(5.0, 0.0) + ]) + }), + attributes : { + color : new ColorGeometryInstanceAttribute(1.0, 1.0, 1.0, 1.0) + }, + id : 'simple polyline' + }); + }); + + it('3D', function() { + render3D(instance); + }); + + it('Columbus view', function() { + renderCV(instance); + }); + + it('2D', function() { + render2D(instance); + }); + + it('pick', function() { + pickGeometry(instance); + }); + }); + }); From b24559405046a354de60ae3922132e98a37c6296 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 8 Jul 2013 15:49:23 -0400 Subject: [PATCH 292/306] Add custom primitive rendering tests. --- Specs/Scene/GeometryRenderingSpec.js | 93 ++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/Specs/Scene/GeometryRenderingSpec.js b/Specs/Scene/GeometryRenderingSpec.js index f2b5893240a3..97e820e8cf82 100644 --- a/Specs/Scene/GeometryRenderingSpec.js +++ b/Specs/Scene/GeometryRenderingSpec.js @@ -688,4 +688,97 @@ defineSuite([ }); }); + describe('Custom geometry', function() { + describe('with indices', function() { + var instance; + beforeAll(function() { + instance = new GeometryInstance({ + geometry : new Geometry({ + attributes : { + position : new GeometryAttribute({ + componentDatatype : ComponentDatatype.DOUBLE, + componentsPerAttribute : 3, + values : new Float64Array([ + 7000000.0, 0.0, 0.0, + 7000000.0, 1000000.0, 0.0, + 7000000.0, 0.0, 1000000.0, + 7000000.0, 1000000.0, 1000000.0 + ]) + }) + }, + indices : new Uint16Array([0, 1, 2, 2, 1, 3]), + primitiveType : PrimitiveType.TRIANGLES + }), + id : 'customWithIndices', + attributes : { + color : new ColorGeometryInstanceAttribute(1.0, 1.0, 1.0, 1.0) + } + }); + instance.geometry.boundingSphere = BoundingSphere.fromVertices(instance.geometry.attributes.position.values); + }); + + it('3D', function() { + render3D(instance); + }); + + it('Columbus view', function() { + renderCV(instance); + }); + + it('2D', function() { + render2D(instance); + }); + + it('pick', function() { + pickGeometry(instance); + }); + }); + + describe('without indices', function() { + var instance; + beforeAll(function() { + instance = new GeometryInstance({ + geometry : new Geometry({ + attributes : { + position : new GeometryAttribute({ + componentDatatype : ComponentDatatype.DOUBLE, + componentsPerAttribute : 3, + values : new Float64Array([ + 7000000.0, 0.0, 0.0, + 7000000.0, 1000000.0, 0.0, + 7000000.0, 0.0, 1000000.0, + 7000000.0, 0.0, 1000000.0, + 7000000.0, 1000000.0, 0.0, + 7000000.0, 1000000.0, 1000000.0 + ]) + }) + }, + primitiveType : PrimitiveType.TRIANGLES + }), + id : 'customWithIndices', + attributes : { + color : new ColorGeometryInstanceAttribute(1.0, 1.0, 1.0, 1.0) + } + }); + instance.geometry.boundingSphere = BoundingSphere.fromVertices(instance.geometry.attributes.position.values); + }); + + it('3D', function() { + render3D(instance); + }); + + it('Columbus view', function() { + renderCV(instance); + }); + + it('2D', function() { + render2D(instance); + }); + + it('pick', function() { + pickGeometry(instance); + }); + }); + }); + }); From cc984e266abb7851ea4a1348e8594faeb04cb02c Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 8 Jul 2013 15:51:06 -0400 Subject: [PATCH 293/306] Revert changes to CesiumViewe. --- Apps/CesiumViewer/CesiumViewer.js | 441 +----------------------------- 1 file changed, 1 insertion(+), 440 deletions(-) diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index 00b4460acf11..9d716b8b057c 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -3,41 +3,6 @@ define([ 'DynamicScene/CzmlDataSource', 'DynamicScene/GeoJsonDataSource', 'Scene/PerformanceDisplay', - 'Core/Color', - 'Core/Math', - 'Core/Cartographic', - 'Core/Cartesian3', - 'Core/Matrix4', - 'Core/Ellipsoid', - 'Core/Extent', - 'Core/Geometry', - 'Core/GeometryAttribute', - 'Core/GeometryInstance', - 'Core/ExtentGeometry', - 'Core/EllipseGeometry', - 'Core/EllipsoidGeometry', - 'Core/PolygonGeometry', - 'Core/BoxGeometry', - 'Core/SimplePolylineGeometry', - 'Core/GeometryPipeline', - 'Core/Transforms', - 'Core/PrimitiveType', - 'Core/ComponentDatatype', - 'Core/ScreenSpaceEventHandler', - 'Core/ScreenSpaceEventType', - 'Core/WallGeometry', - 'Core/VertexFormat', - 'Core/ColorGeometryInstanceAttribute', - 'Core/ShowGeometryInstanceAttribute', - 'Scene/Primitive', - 'Scene/MaterialAppearance', - 'Scene/PerInstanceColorAppearance', - 'Scene/EllipsoidSurfaceAppearance', - 'Scene/DebugAppearance', - 'Scene/Material', - 'Scene/ExtentPrimitive', - 'Scene/Polygon', - 'Scene/createTangentSpaceDebugPrimitive', 'Widgets/checkForChromeFrame', 'Widgets/Viewer/Viewer', 'Widgets/Viewer/viewerDragDropMixin', @@ -47,41 +12,6 @@ define([ CzmlDataSource, GeoJsonDataSource, PerformanceDisplay, - Color, - CesiumMath, - Cartographic, - Cartesian3, - Matrix4, - Ellipsoid, - Extent, - Geometry, - GeometryAttribute, - GeometryInstance, - ExtentGeometry, - EllipseGeometry, - EllipsoidGeometry, - PolygonGeometry, - BoxGeometry, - SimplePolylineGeometry, - GeometryPipeline, - Transforms, - PrimitiveType, - ComponentDatatype, - ScreenSpaceEventHandler, - ScreenSpaceEventType, - WallGeometry, - VertexFormat, - ColorGeometryInstanceAttribute, - ShowGeometryInstanceAttribute, - Primitive, - MaterialAppearance, - PerInstanceColorAppearance, - EllipsoidSurfaceAppearance, - DebugAppearance, - Material, - ExtentPrimitive, - Polygon, - createTangentSpaceDebugPrimitive, checkForChromeFrame, Viewer, viewerDragDropMixin, @@ -207,374 +137,5 @@ define([ window.alert('Unknown theme: ' + theme); } } - - var ellipsoid = viewer.centralBody.getEllipsoid(); - - var geometry = new GeometryInstance({ - geometry : new ExtentGeometry({ - vertexFormat : PerInstanceColorAppearance.VERTEX_FORMAT, - extent : new Extent( - CesiumMath.toRadians(-180.0), - CesiumMath.toRadians(50.0), - CesiumMath.toRadians(180.0), - CesiumMath.toRadians(90.0)), - granularity : 0.006 // More than 64K vertices - }), - id : 'geometry', - attributes : { - color : ColorGeometryInstanceAttribute.fromColor(Color.CORNFLOWERBLUE), - show : new ShowGeometryInstanceAttribute(true) - } - }); - var geometry2 = new GeometryInstance({ - geometry : new EllipsoidGeometry({ - vertexFormat : VertexFormat.ALL, -// vertexFormat : PerInstanceColorAppearance.VERTEX_FORMAT, - ellipsoid : new Ellipsoid(500000.0, 500000.0, 1000000.0) - }), - modelMatrix : Matrix4.multiplyByTranslation(Transforms.eastNorthUpToFixedFrame( - ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-95.59777, 40.03883))), new Cartesian3(0.0, 0.0, 500000.0)), - id : 'geometry2', - attributes : { - color : ColorGeometryInstanceAttribute.fromColor(Color.AQUAMARINE), - show : new ShowGeometryInstanceAttribute(true) - } - }); - var geometry3 = new GeometryInstance({ - geometry : new BoxGeometry({ - vertexFormat : PerInstanceColorAppearance.VERTEX_FORMAT, - dimensions : new Cartesian3(1000000.0, 1000000.0, 2000000.0) - }), - modelMatrix : Matrix4.multiplyByTranslation(Transforms.eastNorthUpToFixedFrame( - ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-75.59777, 40.03883))), new Cartesian3(0.0, 0.0, 3000000.0)), - id : 'geometry3', - attributes : { - color : ColorGeometryInstanceAttribute.fromColor(Color.BLANCHEDALMOND), - show : new ShowGeometryInstanceAttribute(true) - } - }); - var geometry4 = new GeometryInstance({ - geometry : new EllipseGeometry({ - vertexFormat : PerInstanceColorAppearance.VERTEX_FORMAT, - ellipsoid : ellipsoid, - center : ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-100, 20)), - semiMinorAxis : 500000.0, - semiMajorAxis : 1000000.0, - bearing : CesiumMath.PI_OVER_FOUR, - height : 1000000.0 - }), - id : 'geometry4', - attributes : { - color : new ColorGeometryInstanceAttribute(1.0, 1.0, 0.0, 0.5), - show : new ShowGeometryInstanceAttribute(true) - } - }); - var primitive = new Primitive({ - geometryInstances : [geometry, geometry2, geometry3, geometry4], - appearance : new PerInstanceColorAppearance({ - closed : true - }) - }); - scene.getPrimitives().add(primitive); - - scene.getPrimitives().add(createTangentSpaceDebugPrimitive({ - geometry : geometry2.geometry, - length : 10000.0, - modelMatrix : geometry2.modelMatrix - })); - - var m = new Material({ - context : viewer.scene.getContext(), - fabric : { - materials : { - diffuseMaterial : { - type : 'DiffuseMap', - uniforms : { - image : '../Sandcastle/images/bumpmap.png' - } - }, - normalMap : { - type : 'NormalMap', - uniforms : { - image : '../Sandcastle/images/normalmap.png', - strength : 0.6 - } - } - }, - components : { - diffuse : 'diffuseMaterial.diffuse', - specular : 0.01, - normal : 'normalMap.normal' - } - } - }); - var rs = { - depthTest : { - enabled : true - } - }; - var appearance = new MaterialAppearance({ - materialSupport : MaterialAppearance.MaterialSupport.ALL, - material : m, - renderState : rs - }); - var geometry5 = new GeometryInstance({ - geometry : new EllipsoidGeometry({ - vertexFormat : MaterialAppearance.MaterialSupport.ALL.vertexFormat, - ellipsoid : new Ellipsoid(1000000.0, 500000.0, 500000.0) - }), - modelMatrix : Matrix4.multiplyByTranslation(Transforms.eastNorthUpToFixedFrame( - ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-75.59777, 40.03883))), new Cartesian3(0.0, 0.0, 4500000.0)), - id : 'geometry5' - }); - scene.getPrimitives().add(new Primitive({ - geometryInstances : geometry5, - appearance :appearance, - vertexCacheOptimize : false, - releaseGeometryInstances : true - })); - - var polygonGeometry = new GeometryInstance({ - geometry : new PolygonGeometry({ - vertexFormat : EllipsoidSurfaceAppearance.VERTEX_FORMAT, - polygonHierarchy : { - positions : ellipsoid.cartographicArrayToCartesianArray([ - Cartographic.fromDegrees(-109.0, 30.0), - Cartographic.fromDegrees(-95.0, 30.0), - Cartographic.fromDegrees(-95.0, 40.0), - Cartographic.fromDegrees(-109.0, 40.0) - ]), - holes : [{ - positions : ellipsoid.cartographicArrayToCartesianArray([ - Cartographic.fromDegrees(-107.0, 31.0), - Cartographic.fromDegrees(-107.0, 39.0), - Cartographic.fromDegrees(-97.0, 39.0), - Cartographic.fromDegrees(-97.0, 31.0) - ]), - holes : [{ - positions : ellipsoid.cartographicArrayToCartesianArray([ - Cartographic.fromDegrees(-105.0, 33.0), - Cartographic.fromDegrees(-99.0, 33.0), - Cartographic.fromDegrees(-99.0, 37.0), - Cartographic.fromDegrees(-105.0, 37.0) - ]), - holes : [{ - positions : ellipsoid.cartographicArrayToCartesianArray([ - Cartographic.fromDegrees(-103.0, 34.0), - Cartographic.fromDegrees(-101.0, 34.0), - Cartographic.fromDegrees(-101.0, 36.0), - Cartographic.fromDegrees(-103.0, 36.0) - ]) - }] - }] - }] - }, - height : 3000000.0, - stRotation : 0.523598776 - }), - id : 'polygon3' - }); - var polygonPrimitive = new Primitive({ - geometryInstances : polygonGeometry, - appearance : new EllipsoidSurfaceAppearance({ - material : Material.fromType(scene.getContext(), 'Stripe'), - aboveGround : true, - translucent : false, - flat : true - }) - }); - scene.getPrimitives().add(polygonPrimitive); - - var wall = new GeometryInstance({ - geometry : new WallGeometry({ - vertexFormat : MaterialAppearance.MaterialSupport.TEXTURED.vertexFormat, - positions : ellipsoid.cartographicArrayToCartesianArray([ - Cartographic.fromDegrees(-125.0, 37.0, 100000.0), - Cartographic.fromDegrees(-125.0, 38.0, 100000.0), - Cartographic.fromDegrees(-120.0, 38.0, 100000.0), - Cartographic.fromDegrees(-120.0, 37.0, 100000.0), - Cartographic.fromDegrees(-125.0, 37.0, 100000.0) - ]) - }) - // id is undefined here for testing - }); - var wallPrimitive = new Primitive({ - geometryInstances : wall, - appearance : new MaterialAppearance({ - materialSupport : MaterialAppearance.MaterialSupport.TEXTURED, - material : Material.fromType(scene.getContext(), 'Checkerboard'), - faceForward : true - }), - allowColumbusView : false - }); - wallPrimitive.appearance.material.uniforms.repeat = { x : 20.0, y : 6.0 }; - scene.getPrimitives().add(wallPrimitive); - - scene.getPrimitives().add(new Primitive({ - geometryInstances : new GeometryInstance({ - geometry : new WallGeometry({ - vertexFormat : VertexFormat.ALL, - positions : ellipsoid.cartographicArrayToCartesianArray([ - Cartographic.fromDegrees(-5.0, -5.0, 500000.0), - Cartographic.fromDegrees( 5.0, -5.0, 600000.0), - Cartographic.fromDegrees( 5.0, 5.0, 600000.0), - Cartographic.fromDegrees(-5.0, 5.0, 500000.0), - Cartographic.fromDegrees(-5.0, -5.0, 500000.0) - ]), - bottom : 400000.0 - }) - }), - appearance : new DebugAppearance({ - attributeName : 'normal' - }) - })); - - var customWithIndices = new GeometryInstance({ - geometry : new Geometry({ - attributes : { - position : new GeometryAttribute({ - componentDatatype : ComponentDatatype.DOUBLE, - componentsPerAttribute : 3, - values : new Float64Array([ - 7000000.0, 0.0, 0.0, - 7000000.0, 1000000.0, 0.0, - 7000000.0, 0.0, 1000000.0 - ]) - }) - }, - indices : new Uint16Array([0, 1, 1, 2, 2, 0]), - primitiveType : PrimitiveType.LINES - }), - id : 'customWithIndices', - attributes : { - color : new ColorGeometryInstanceAttribute(1.0, 1.0, 1.0, 1.0) - } - }); - scene.getPrimitives().add(new Primitive({ - geometryInstances : customWithIndices, - appearance : new PerInstanceColorAppearance({ - flat : true - }) - })); - - var customWithoutIndices = new GeometryInstance({ - geometry : new Geometry({ - attributes : { - position : new GeometryAttribute({ - componentDatatype : ComponentDatatype.DOUBLE, - componentsPerAttribute : 3, - values : new Float64Array([ - 7500000.0, 0.0, 0.0, - 7500000.0, 1000000.0, 0.0, - 7500000.0, 0.0, 1000000.0 - ]) - }) - }, - primitiveType : PrimitiveType.LINE_LOOP - }), - id : 'customWithoutIndices', - attributes : { - color : new ColorGeometryInstanceAttribute(1.0, 1.0, 0.0, 1.0) - } - }); - scene.getPrimitives().add(new Primitive({ - geometryInstances : customWithoutIndices, - appearance : new PerInstanceColorAppearance({ - renderState : {}, // No depth test - flat : true - }) - })); - - scene.getPrimitives().add(new Primitive({ - geometryInstances : [ - new GeometryInstance({ - geometry : new SimplePolylineGeometry({ - positions : ellipsoid.cartographicArrayToCartesianArray([ - Cartographic.fromDegrees(0.0, 0.0), - Cartographic.fromDegrees(5.0, 0.0), - Cartographic.fromDegrees(5.0, 5.0) - ]) - }), - attributes : { - color : new ColorGeometryInstanceAttribute(1.0, 1.0, 1.0, 1.0) - }, - id : 'simple polyline' - }), - new GeometryInstance({ - geometry : new SimplePolylineGeometry({ - positions : ellipsoid.cartographicArrayToCartesianArray([ - Cartographic.fromDegrees(0.0, 0.0), - Cartographic.fromDegrees(0.0, 5.0), - Cartographic.fromDegrees(5.0, 5.0) - ]) - }), - attributes : { - color : new ColorGeometryInstanceAttribute(1.0, 0.0, 1.0, 1.0) - }, - id : 'another simple polyline' - }) - ], - appearance : new PerInstanceColorAppearance({ - flat : true, - translucent : false - }) - })); - - var extentPrimitive = new ExtentPrimitive({ - extent : Extent.fromDegrees(0.0, 20.0, 10.0, 30.0) - }); - scene.getPrimitives().add(extentPrimitive); - - var pp = new Polygon({ - positions : ellipsoid.cartographicArrayToCartesianArray([ - Cartographic.fromDegrees(0.0, 45.0), - Cartographic.fromDegrees(10.0, 45.0), - Cartographic.fromDegrees(10.0, 55.0) - ]) - }); - scene.getPrimitives().add(pp); - - var handler = new ScreenSpaceEventHandler(scene.getCanvas()); - /* - handler.setInputAction( - function (movement) { - var pickedObject = scene.pick(movement.endPosition); - if (typeof pickedObject !== 'undefined') { - console.log(pickedObject); - } - }, - ScreenSpaceEventType.MOUSE_MOVE - ); - */ - handler.setInputAction( - function (e) { - /* - polygonPrimitive.appearance.material = Material.fromType(scene.getContext(), 'Wood'); - wallPrimitive.appearance = new MaterialAppearance(); - - extentPrimitive.material = Material.fromType(scene.getContext(), 'Dot'); - extentPrimitive.rotation = CesiumMath.toRadians(45.0); - extentPrimitive.height = 1500000.0; - - pp.material = Material.fromType(scene.getContext(), 'Dot'); - pp.textureRotationAngle = CesiumMath.toRadians(30.0); - pp.height = 1500000.0; - */ - - var pickedObject = scene.pick(e.position); - if (typeof pickedObject !== 'undefined') { - var attributes = primitive.getGeometryInstanceAttributes(pickedObject); - if (typeof attributes.color !== 'undefined') { - attributes.color = [ - Math.floor((Math.random()*100)), - Math.floor((Math.random()*100)), - Math.floor((Math.random()*100)), - 255 - ]; - } - } - }, - ScreenSpaceEventType.LEFT_CLICK - ); } -}); +}); \ No newline at end of file From 0030cb7cd71277c4803569f81c2df1cece788fee Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 8 Jul 2013 20:41:29 -0400 Subject: [PATCH 294/306] Updates based on review. --- Apps/Sandcastle/gallery/Custom Rendering.html | 48 +- .../gallery/Geometry and Appearances.html | 5 +- CHANGES.md | 24 +- Source/Core/BoundingSphere.js | 36 +- Source/Core/BoxGeometry.js | 672 +++++++++++++----- Source/Core/CircleGeometry.js | 4 +- Source/Core/EllipseGeometry.js | 8 +- Source/Core/EllipsoidGeometry.js | 9 +- Source/Core/ExtentGeometry.js | 8 +- Source/Core/Geometry.js | 9 +- Source/Core/GeometryAttributes.js | 82 +++ Source/Core/PolygonGeometry.js | 8 +- Source/Core/SimplePolylineGeometry.js | 21 +- Source/Core/WallGeometry.js | 8 +- Source/Renderer/Context.js | 2 +- Source/Scene/SkyBox.js | 2 +- Specs/Core/BoundingSphereSpec.js | 2 +- Specs/Core/BoxGeometrySpec.js | 39 +- Specs/Scene/GeometryRenderingSpec.js | 2 +- 19 files changed, 690 insertions(+), 299 deletions(-) create mode 100644 Source/Core/GeometryAttributes.js diff --git a/Apps/Sandcastle/gallery/Custom Rendering.html b/Apps/Sandcastle/gallery/Custom Rendering.html index d200947dba90..f8a8e9f78f7e 100644 --- a/Apps/Sandcastle/gallery/Custom Rendering.html +++ b/Apps/Sandcastle/gallery/Custom Rendering.html @@ -27,11 +27,7 @@

    Loading...

    diff --git a/Apps/Sandcastle/gallery/Geometry and Appearances.html b/Apps/Sandcastle/gallery/Geometry and Appearances.html index 4aa39e443541..0e23d7b12724 100644 --- a/Apps/Sandcastle/gallery/Geometry and Appearances.html +++ b/Apps/Sandcastle/gallery/Geometry and Appearances.html @@ -145,8 +145,9 @@ // Create box and ellipsoid boxes, and use the instance's // modelMatrix to scale and position them. - var boxGeometry = new Cesium.BoxGeometry({ - vertexFormat : Cesium.PerInstanceColorAppearance.VERTEX_FORMAT + var boxGeometry = Cesium.BoxGeometry.fromDimensions({ + vertexFormat : Cesium.PerInstanceColorAppearance.VERTEX_FORMAT, + dimensions : new Cesium.Cartesian3(1.0, 1.0, 1.0) }); var ellipsoidGeometry = new Cesium.EllipsoidGeometry({ vertexFormat : Cesium.PerInstanceColorAppearance.VERTEX_FORMAT, diff --git a/CHANGES.md b/CHANGES.md index a492dae500c8..37d618d72b79 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -22,28 +22,10 @@ Beta Releases * Removed `height` and `textureRotationAngle` arguments from `Polygon` `setPositions` and `configureFromPolygonHierarchy` functions. Use `Polygon` `height` and `textureRotationAngle` properties. * Renamed `PolygonPipeline.cleanUp` to `PolygonPipeline.removeDuplicates`. * Removed `PolygonPipeline.wrapLongitude`. Use `GeometryPipeline.wrapLongitude` instead. - * Added `height` parameter to `BoundingSphere.fromExtent3D`. - * Added `height` parameter to `Extent.subsample`. + * Added `surfaceHeight` parameter to `BoundingSphere.fromExtent3D`. + * Added `surfaceHeight` parameter to `Extent.subsample`. * Added `ExtentPrimitive`. -* Added `Geometry` and `GeometryInstance`. Added the following geometry types: - * `PolygonGeometry` - * `ExtentGeometry` - * `EllipseGeometry` - * `CircleGeometry` - * `WallGeometry` - * `SimplePolylineGeometry` - * `BoxGeometry` - * `EllipsoidGeometry` -* Added appearances, which describe the visual characteristics for geometry instances. Added the following types: - * `Appearance` - * `PerInstanceColorAppearance` - * `EllipsoidSurfaceAppearance` -* Added `Primitive`, which is a generic primitive that combines geometry instances and appearances. -* Added `GeometryPipeline.combine` to combine meshes for better batching. -* Added `GeometryPipeline.computeNormal` to compute normals for a geometry. -* Added `GeometryPipeline.computeBinormalAndTangent` to compute binormals and tangent vectors for a geometry. -* Added `GeometryPipeline.wrapLongitude` to split geometry across the International Date Line. -* Added `GeometryPipeline.createLineSegmentsForVectors` and `createTangentSpaceDebugPrimitive` for debugging. +* Added Geometry and Appearances [#911](https://github.com/AnalyticalGraphicsInc/cesium/pull/911). * Added `PolylinePipeline.removeDuplicates`. * Added `barycentricCoordinates` to compute the barycentric coordinates of a point in a triangle. * Added `BoundingSphere.fromEllipsoid`. diff --git a/Source/Core/BoundingSphere.js b/Source/Core/BoundingSphere.js index dac59209acc8..d683aaad0804 100644 --- a/Source/Core/BoundingSphere.js +++ b/Source/Core/BoundingSphere.js @@ -524,7 +524,7 @@ define([ }; /** - * Creaates a bounding sphere encompassing an ellipsoid. + * Creates a bounding sphere encompassing an ellipsoid. * * @memberof BoundingSphere * @@ -547,6 +547,7 @@ define([ result = new BoundingSphere(); } + Cartesian3.clone(Cartesian3.ZERO, result.center); result.radius = ellipsoid.getMaximumRadius(); return result; }; @@ -763,16 +764,17 @@ define([ return result; }; - var projectTo2DNormal = new Cartesian3(); - var projectTo2DEast = new Cartesian3(); - var projectTo2DNorth = new Cartesian3(); - var projectTo2DWest = new Cartesian3(); - var projectTo2DSouth = new Cartesian3(); - var projectTo2DCartographic = new Cartographic(); - var projectTo2DPositions = new Array(8); + var projectTo2DNormalScratch = new Cartesian3(); + var projectTo2DEastScratch = new Cartesian3(); + var projectTo2DNorthScratch = new Cartesian3(); + var projectTo2DWestScratch = new Cartesian3(); + var projectTo2DSouthScratch = new Cartesian3(); + var projectTo2DCartographicScratch = new Cartographic(); + var projectTo2DPositionsScratch = new Array(8); for (var n = 0; n < 8; ++n) { - projectTo2DPositions[n] = new Cartesian3(); + projectTo2DPositionsScratch[n] = new Cartesian3(); } + var projectTo2DProjection = new GeographicProjection(); /** * Creates a bounding sphere in 2D from a bounding sphere in 3D world coordinates. * @memberof BoundingSphere @@ -789,26 +791,26 @@ define([ throw new DeveloperError('sphere is required.'); } - projection = (typeof projection !== 'undefined') ? projection : new GeographicProjection(); + projection = defaultValue(projection, projectTo2DProjection); var ellipsoid = projection.getEllipsoid(); var center = sphere.center; var radius = sphere.radius; - var normal = ellipsoid.geodeticSurfaceNormal(center, projectTo2DNormal); - var east = Cartesian3.cross(Cartesian3.UNIT_Z, normal, projectTo2DEast); + var normal = ellipsoid.geodeticSurfaceNormal(center, projectTo2DNormalScratch); + var east = Cartesian3.cross(Cartesian3.UNIT_Z, normal, projectTo2DEastScratch); Cartesian3.normalize(east, east); - var north = Cartesian3.cross(normal, east, projectTo2DNorth); + var north = Cartesian3.cross(normal, east, projectTo2DNorthScratch); Cartesian3.normalize(north, north); Cartesian3.multiplyByScalar(normal, radius, normal); Cartesian3.multiplyByScalar(north, radius, north); Cartesian3.multiplyByScalar(east, radius, east); - var south = Cartesian3.negate(north, projectTo2DSouth); - var west = Cartesian3.negate(east, projectTo2DWest); + var south = Cartesian3.negate(north, projectTo2DSouthScratch); + var west = Cartesian3.negate(east, projectTo2DWestScratch); - var positions = projectTo2DPositions; + var positions = projectTo2DPositionsScratch; // top NE corner var corner = positions[0]; @@ -856,7 +858,7 @@ define([ for (var i = 0; i < length; ++i) { var position = positions[i]; Cartesian3.add(center, position, position); - var cartographic = ellipsoid.cartesianToCartographic(position, projectTo2DCartographic); + var cartographic = ellipsoid.cartesianToCartographic(position, projectTo2DCartographicScratch); projection.project(cartographic, position); } diff --git a/Source/Core/BoxGeometry.js b/Source/Core/BoxGeometry.js index c3303fbf8af8..58198e971045 100644 --- a/Source/Core/BoxGeometry.js +++ b/Source/Core/BoxGeometry.js @@ -7,6 +7,7 @@ define([ './defaultValue', './BoundingSphere', './GeometryAttribute', + './GeometryAttributes', './VertexFormat' ], function( DeveloperError, @@ -16,53 +17,49 @@ define([ defaultValue, BoundingSphere, GeometryAttribute, + GeometryAttributes, VertexFormat) { "use strict"; + var diffScratch = new Cartesian3(); + /** * Creates vertices and indices for a cube centered at the origin. * * @alias BoxGeometry * @constructor * - * @param {Cartesian3} [options.minimumCorner] The minimum x, y, and z coordinates of the box. - * @param {Cartesian3} [options.maximumCorner] The maximum x, y, and z coordinates of the box. - * @param {Cartesian3} [options.dimensions=new Cartesian3(1.0, 1.0, 1.0)] The width, depth, and height of the box stored in the x, y, and z coordinates of the Cartesian3, respectively. + * @param {Cartesian3} options.minimumCorner The minimum x, y, and z coordinates of the box. + * @param {Cartesian3} options.maximumCorner The maximum x, y, and z coordinates of the box. * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed. * - * @exception {DeveloperError} All dimensions components must be greater than or equal to zero. + * @exception {DeveloperError} options.minimumCorner is required. + * @exception {DeveloperError} options.maximumCorner is required. * * @example * var box = new BoxGeometry({ * vertexFormat : VertexFormat.POSITION_ONLY, - * dimensions : new Cartesian3(500000.0, 500000.0, 500000.0), - * modelMatrix : Transforms.eastNorthUpToFixedFrame(center) + * maximumCorner : new Cartesian3(250000.0, 250000.0, 250000.0), + * minimumCorner : new Cartesian3(-250000.0, -250000.0, -250000.0) * }); */ var BoxGeometry = function(options) { options = defaultValue(options, defaultValue.EMPTY_OBJECT); - var min; - var max; - - if (typeof options.minimumCorner !== 'undefined' && typeof options.maximumCorner !== 'undefined') { - min = options.minimumCorner; - max = options.maximumCorner; - } else { - var dimensions = typeof options.dimensions !== 'undefined' ? options.dimensions : new Cartesian3(1.0, 1.0, 1.0); + var min = options.minimumCorner; + var max = options.maximumCorner; - if (dimensions.x < 0 || dimensions.y < 0 || dimensions.z < 0) { - throw new DeveloperError('All dimensions components must be greater than or equal to zero.'); - } + if (typeof min === 'undefined') { + throw new DeveloperError('options.minimumCorner is required.'); + } - var corner = dimensions.multiplyByScalar(0.5); - min = corner.negate(); - max = corner; + if (typeof max === 'undefined') { + throw new DeveloperError('options.maximumCorner is required'); } var vertexFormat = defaultValue(options.vertexFormat, VertexFormat.DEFAULT); - var attributes = {}; + var attributes = new GeometryAttributes(); var indices; var positions; @@ -72,40 +69,88 @@ define([ positions = new Float64Array(6 * 4 * 3); // +z face - positions[0] = min.x; positions[1] = min.y; positions[2] = max.z; - positions[3] = max.x; positions[4] = min.y; positions[5] = max.z; - positions[6] = max.x; positions[7] = max.y; positions[8] = max.z; - positions[9] = min.x; positions[10] = max.y; positions[11] = max.z; + positions[0] = min.x; + positions[1] = min.y; + positions[2] = max.z; + positions[3] = max.x; + positions[4] = min.y; + positions[5] = max.z; + positions[6] = max.x; + positions[7] = max.y; + positions[8] = max.z; + positions[9] = min.x; + positions[10] = max.y; + positions[11] = max.z; // -z face - positions[12] = min.x; positions[13] = min.y; positions[14] = min.z; - positions[15] = max.x; positions[16] = min.y; positions[17] = min.z; - positions[18] = max.x; positions[19] = max.y; positions[20] = min.z; - positions[21] = min.x; positions[22] = max.y; positions[23] = min.z; + positions[12] = min.x; + positions[13] = min.y; + positions[14] = min.z; + positions[15] = max.x; + positions[16] = min.y; + positions[17] = min.z; + positions[18] = max.x; + positions[19] = max.y; + positions[20] = min.z; + positions[21] = min.x; + positions[22] = max.y; + positions[23] = min.z; // +x face - positions[24] = max.x; positions[25] = min.y; positions[26] = min.z; - positions[27] = max.x; positions[28] = max.y; positions[29] = min.z; - positions[30] = max.x; positions[31] = max.y; positions[32] = max.z; - positions[33] = max.x; positions[34] = min.y; positions[35] = max.z; + positions[24] = max.x; + positions[25] = min.y; + positions[26] = min.z; + positions[27] = max.x; + positions[28] = max.y; + positions[29] = min.z; + positions[30] = max.x; + positions[31] = max.y; + positions[32] = max.z; + positions[33] = max.x; + positions[34] = min.y; + positions[35] = max.z; // -x face - positions[36] = min.x; positions[37] = min.y; positions[38] = min.z; - positions[39] = min.x; positions[40] = max.y; positions[41] = min.z; - positions[42] = min.x; positions[43] = max.y; positions[44] = max.z; - positions[45] = min.x; positions[46] = min.y; positions[47] = max.z; + positions[36] = min.x; + positions[37] = min.y; + positions[38] = min.z; + positions[39] = min.x; + positions[40] = max.y; + positions[41] = min.z; + positions[42] = min.x; + positions[43] = max.y; + positions[44] = max.z; + positions[45] = min.x; + positions[46] = min.y; + positions[47] = max.z; // +y face - positions[48] = min.x; positions[49] = max.y; positions[50] = min.z; - positions[51] = max.x; positions[52] = max.y; positions[53] = min.z; - positions[54] = max.x; positions[55] = max.y; positions[56] = max.z; - positions[57] = min.x; positions[58] = max.y; positions[59] = max.z; + positions[48] = min.x; + positions[49] = max.y; + positions[50] = min.z; + positions[51] = max.x; + positions[52] = max.y; + positions[53] = min.z; + positions[54] = max.x; + positions[55] = max.y; + positions[56] = max.z; + positions[57] = min.x; + positions[58] = max.y; + positions[59] = max.z; // -y face - positions[60] = min.x; positions[61] = min.y; positions[62] = min.z; - positions[63] = max.x; positions[64] = min.y; positions[65] = min.z; - positions[66] = max.x; positions[67] = min.y; positions[68] = max.z; - positions[69] = min.x; positions[70] = min.y; positions[71] = max.z; + positions[60] = min.x; + positions[61] = min.y; + positions[62] = min.z; + positions[63] = max.x; + positions[64] = min.y; + positions[65] = min.z; + positions[66] = max.x; + positions[67] = min.y; + positions[68] = max.z; + positions[69] = min.x; + positions[70] = min.y; + positions[71] = max.z; attributes.position = new GeometryAttribute({ componentDatatype : ComponentDatatype.DOUBLE, @@ -118,40 +163,88 @@ define([ var normals = new Float32Array(6 * 4 * 3); // +z face - normals[0] = 0.0; normals[1] = 0.0; normals[2] = 1.0; - normals[3] = 0.0; normals[4] = 0.0; normals[5] = 1.0; - normals[6] = 0.0; normals[7] = 0.0; normals[8] = 1.0; - normals[9] = 0.0; normals[10] = 0.0; normals[11] = 1.0; + normals[0] = 0.0; + normals[1] = 0.0; + normals[2] = 1.0; + normals[3] = 0.0; + normals[4] = 0.0; + normals[5] = 1.0; + normals[6] = 0.0; + normals[7] = 0.0; + normals[8] = 1.0; + normals[9] = 0.0; + normals[10] = 0.0; + normals[11] = 1.0; // -z face - normals[12] = 0.0; normals[13] = 0.0; normals[14] = -1.0; - normals[15] = 0.0; normals[16] = 0.0; normals[17] = -1.0; - normals[18] = 0.0; normals[19] = 0.0; normals[20] = -1.0; - normals[21] = 0.0; normals[22] = 0.0; normals[23] = -1.0; + normals[12] = 0.0; + normals[13] = 0.0; + normals[14] = -1.0; + normals[15] = 0.0; + normals[16] = 0.0; + normals[17] = -1.0; + normals[18] = 0.0; + normals[19] = 0.0; + normals[20] = -1.0; + normals[21] = 0.0; + normals[22] = 0.0; + normals[23] = -1.0; // +x face - normals[24] = 1.0; normals[25] = 0.0; normals[26] = 0.0; - normals[27] = 1.0; normals[28] = 0.0; normals[29] = 0.0; - normals[30] = 1.0; normals[31] = 0.0; normals[32] = 0.0; - normals[33] = 1.0; normals[34] = 0.0; normals[35] = 0.0; + normals[24] = 1.0; + normals[25] = 0.0; + normals[26] = 0.0; + normals[27] = 1.0; + normals[28] = 0.0; + normals[29] = 0.0; + normals[30] = 1.0; + normals[31] = 0.0; + normals[32] = 0.0; + normals[33] = 1.0; + normals[34] = 0.0; + normals[35] = 0.0; // -x face - normals[36] = -1.0; normals[37] = 0.0; normals[38] = 0.0; - normals[39] = -1.0; normals[40] = 0.0; normals[41] = 0.0; - normals[42] = -1.0; normals[43] = 0.0; normals[44] = 0.0; - normals[45] = -1.0; normals[46] = 0.0; normals[47] = 0.0; + normals[36] = -1.0; + normals[37] = 0.0; + normals[38] = 0.0; + normals[39] = -1.0; + normals[40] = 0.0; + normals[41] = 0.0; + normals[42] = -1.0; + normals[43] = 0.0; + normals[44] = 0.0; + normals[45] = -1.0; + normals[46] = 0.0; + normals[47] = 0.0; // +y face - normals[48] = 0.0; normals[49] = 1.0; normals[50] = 0.0; - normals[51] = 0.0; normals[52] = 1.0; normals[53] = 0.0; - normals[54] = 0.0; normals[55] = 1.0; normals[56] = 0.0; - normals[57] = 0.0; normals[58] = 1.0; normals[59] = 0.0; + normals[48] = 0.0; + normals[49] = 1.0; + normals[50] = 0.0; + normals[51] = 0.0; + normals[52] = 1.0; + normals[53] = 0.0; + normals[54] = 0.0; + normals[55] = 1.0; + normals[56] = 0.0; + normals[57] = 0.0; + normals[58] = 1.0; + normals[59] = 0.0; // -y face - normals[60] = 0.0; normals[61] = -1.0; normals[62] = 0.0; - normals[63] = 0.0; normals[64] = -1.0; normals[65] = 0.0; - normals[66] = 0.0; normals[67] = -1.0; normals[68] = 0.0; - normals[69] = 0.0; normals[70] = -1.0; normals[71] = 0.0; + normals[60] = 0.0; + normals[61] = -1.0; + normals[62] = 0.0; + normals[63] = 0.0; + normals[64] = -1.0; + normals[65] = 0.0; + normals[66] = 0.0; + normals[67] = -1.0; + normals[68] = 0.0; + normals[69] = 0.0; + normals[70] = -1.0; + normals[71] = 0.0; attributes.normal = new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, @@ -164,40 +257,64 @@ define([ var texCoords = new Float32Array(6 * 4 * 2); // +z face - texCoords[0] = 0.0; texCoords[1] = 0.0; - texCoords[2] = 1.0; texCoords[3] = 0.0; - texCoords[4] = 1.0; texCoords[5] = 1.0; - texCoords[6] = 0.0; texCoords[7] = 1.0; + texCoords[0] = 0.0; + texCoords[1] = 0.0; + texCoords[2] = 1.0; + texCoords[3] = 0.0; + texCoords[4] = 1.0; + texCoords[5] = 1.0; + texCoords[6] = 0.0; + texCoords[7] = 1.0; // -z face - texCoords[8] = 1.0; texCoords[9] = 0.0; - texCoords[10] = 0.0; texCoords[11] = 0.0; - texCoords[12] = 0.0; texCoords[13] = 1.0; - texCoords[14] = 1.0; texCoords[15] = 1.0; + texCoords[8] = 1.0; + texCoords[9] = 0.0; + texCoords[10] = 0.0; + texCoords[11] = 0.0; + texCoords[12] = 0.0; + texCoords[13] = 1.0; + texCoords[14] = 1.0; + texCoords[15] = 1.0; //+x face - texCoords[16] = 0.0; texCoords[17] = 0.0; - texCoords[18] = 1.0; texCoords[19] = 0.0; - texCoords[20] = 1.0; texCoords[21] = 1.0; - texCoords[22] = 0.0; texCoords[23] = 1.0; + texCoords[16] = 0.0; + texCoords[17] = 0.0; + texCoords[18] = 1.0; + texCoords[19] = 0.0; + texCoords[20] = 1.0; + texCoords[21] = 1.0; + texCoords[22] = 0.0; + texCoords[23] = 1.0; // -x face - texCoords[24] = 1.0; texCoords[25] = 0.0; - texCoords[26] = 0.0; texCoords[27] = 0.0; - texCoords[28] = 0.0; texCoords[29] = 1.0; - texCoords[30] = 1.0; texCoords[31] = 1.0; + texCoords[24] = 1.0; + texCoords[25] = 0.0; + texCoords[26] = 0.0; + texCoords[27] = 0.0; + texCoords[28] = 0.0; + texCoords[29] = 1.0; + texCoords[30] = 1.0; + texCoords[31] = 1.0; // +y face - texCoords[32] = 1.0; texCoords[33] = 0.0; - texCoords[34] = 0.0; texCoords[35] = 0.0; - texCoords[36] = 0.0; texCoords[37] = 1.0; - texCoords[38] = 1.0; texCoords[39] = 1.0; + texCoords[32] = 1.0; + texCoords[33] = 0.0; + texCoords[34] = 0.0; + texCoords[35] = 0.0; + texCoords[36] = 0.0; + texCoords[37] = 1.0; + texCoords[38] = 1.0; + texCoords[39] = 1.0; // -y face - texCoords[40] = 0.0; texCoords[41] = 0.0; - texCoords[42] = 1.0; texCoords[43] = 0.0; - texCoords[44] = 1.0; texCoords[45] = 1.0; - texCoords[46] = 0.0; texCoords[47] = 1.0; + texCoords[40] = 0.0; + texCoords[41] = 0.0; + texCoords[42] = 1.0; + texCoords[43] = 0.0; + texCoords[44] = 1.0; + texCoords[45] = 1.0; + texCoords[46] = 0.0; + texCoords[47] = 1.0; attributes.st = new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, @@ -210,40 +327,88 @@ define([ var tangents = new Float32Array(6 * 4 * 3); // +z face - tangents[0] = 1.0; tangents[1] = 0.0; tangents[2] = 0.0; - tangents[3] = 1.0; tangents[4] = 0.0; tangents[5] = 0.0; - tangents[6] = 1.0; tangents[7] = 0.0; tangents[8] = 0.0; - tangents[9] = 1.0; tangents[10] = 0.0; tangents[11] = 0.0; + tangents[0] = 1.0; + tangents[1] = 0.0; + tangents[2] = 0.0; + tangents[3] = 1.0; + tangents[4] = 0.0; + tangents[5] = 0.0; + tangents[6] = 1.0; + tangents[7] = 0.0; + tangents[8] = 0.0; + tangents[9] = 1.0; + tangents[10] = 0.0; + tangents[11] = 0.0; // -z face - tangents[12] = -1.0; tangents[13] = 0.0; tangents[14] = 0.0; - tangents[15] = -1.0; tangents[16] = 0.0; tangents[17] = 0.0; - tangents[18] = -1.0; tangents[19] = 0.0; tangents[20] = 0.0; - tangents[21] = -1.0; tangents[22] = 0.0; tangents[23] = 0.0; + tangents[12] = -1.0; + tangents[13] = 0.0; + tangents[14] = 0.0; + tangents[15] = -1.0; + tangents[16] = 0.0; + tangents[17] = 0.0; + tangents[18] = -1.0; + tangents[19] = 0.0; + tangents[20] = 0.0; + tangents[21] = -1.0; + tangents[22] = 0.0; + tangents[23] = 0.0; // +x face - tangents[24] = 0.0; tangents[25] = 1.0; tangents[26] = 0.0; - tangents[27] = 0.0; tangents[28] = 1.0; tangents[29] = 0.0; - tangents[30] = 0.0; tangents[31] = 1.0; tangents[32] = 0.0; - tangents[33] = 0.0; tangents[34] = 1.0; tangents[35] = 0.0; + tangents[24] = 0.0; + tangents[25] = 1.0; + tangents[26] = 0.0; + tangents[27] = 0.0; + tangents[28] = 1.0; + tangents[29] = 0.0; + tangents[30] = 0.0; + tangents[31] = 1.0; + tangents[32] = 0.0; + tangents[33] = 0.0; + tangents[34] = 1.0; + tangents[35] = 0.0; // -x face - tangents[36] = 0.0; tangents[37] = -1.0; tangents[38] = 0.0; - tangents[39] = 0.0; tangents[40] = -1.0; tangents[41] = 0.0; - tangents[42] = 0.0; tangents[43] = -1.0; tangents[44] = 0.0; - tangents[45] = 0.0; tangents[46] = -1.0; tangents[47] = 0.0; + tangents[36] = 0.0; + tangents[37] = -1.0; + tangents[38] = 0.0; + tangents[39] = 0.0; + tangents[40] = -1.0; + tangents[41] = 0.0; + tangents[42] = 0.0; + tangents[43] = -1.0; + tangents[44] = 0.0; + tangents[45] = 0.0; + tangents[46] = -1.0; + tangents[47] = 0.0; // +y face - tangents[48] = -1.0; tangents[49] = 0.0; tangents[50] = 0.0; - tangents[51] = -1.0; tangents[52] = 0.0; tangents[53] = 0.0; - tangents[54] = -1.0; tangents[55] = 0.0; tangents[56] = 0.0; - tangents[57] = -1.0; tangents[58] = 0.0; tangents[59] = 0.0; + tangents[48] = -1.0; + tangents[49] = 0.0; + tangents[50] = 0.0; + tangents[51] = -1.0; + tangents[52] = 0.0; + tangents[53] = 0.0; + tangents[54] = -1.0; + tangents[55] = 0.0; + tangents[56] = 0.0; + tangents[57] = -1.0; + tangents[58] = 0.0; + tangents[59] = 0.0; // -y face - tangents[60] = 1.0; tangents[61] = 0.0; tangents[62] = 0.0; - tangents[63] = 1.0; tangents[64] = 0.0; tangents[65] = 0.0; - tangents[66] = 1.0; tangents[67] = 0.0; tangents[68] = 0.0; - tangents[69] = 1.0; tangents[70] = 0.0; tangents[71] = 0.0; + tangents[60] = 1.0; + tangents[61] = 0.0; + tangents[62] = 0.0; + tangents[63] = 1.0; + tangents[64] = 0.0; + tangents[65] = 0.0; + tangents[66] = 1.0; + tangents[67] = 0.0; + tangents[68] = 0.0; + tangents[69] = 1.0; + tangents[70] = 0.0; + tangents[71] = 0.0; attributes.tangent = new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, @@ -256,40 +421,88 @@ define([ var binormals = new Float32Array(6 * 4 * 3); // +z face - binormals[0] = 0.0; binormals[1] = 1.0; binormals[2] = 0.0; - binormals[3] = 0.0; binormals[4] = 1.0; binormals[5] = 0.0; - binormals[6] = 0.0; binormals[7] = 1.0; binormals[8] = 0.0; - binormals[9] = 0.0; binormals[10] = 1.0; binormals[11] = 0.0; + binormals[0] = 0.0; + binormals[1] = 1.0; + binormals[2] = 0.0; + binormals[3] = 0.0; + binormals[4] = 1.0; + binormals[5] = 0.0; + binormals[6] = 0.0; + binormals[7] = 1.0; + binormals[8] = 0.0; + binormals[9] = 0.0; + binormals[10] = 1.0; + binormals[11] = 0.0; // -z face - binormals[12] = 0.0; binormals[13] = 1.0; binormals[14] = 0.0; - binormals[15] = 0.0; binormals[16] = 1.0; binormals[17] = 0.0; - binormals[18] = 0.0; binormals[19] = 1.0; binormals[20] = 0.0; - binormals[21] = 0.0; binormals[22] = 1.0; binormals[23] = 0.0; + binormals[12] = 0.0; + binormals[13] = 1.0; + binormals[14] = 0.0; + binormals[15] = 0.0; + binormals[16] = 1.0; + binormals[17] = 0.0; + binormals[18] = 0.0; + binormals[19] = 1.0; + binormals[20] = 0.0; + binormals[21] = 0.0; + binormals[22] = 1.0; + binormals[23] = 0.0; // +x face - binormals[24] = 0.0; binormals[25] = 0.0; binormals[26] = 1.0; - binormals[27] = 0.0; binormals[28] = 0.0; binormals[29] = 1.0; - binormals[30] = 0.0; binormals[31] = 0.0; binormals[32] = 1.0; - binormals[33] = 0.0; binormals[34] = 0.0; binormals[35] = 1.0; + binormals[24] = 0.0; + binormals[25] = 0.0; + binormals[26] = 1.0; + binormals[27] = 0.0; + binormals[28] = 0.0; + binormals[29] = 1.0; + binormals[30] = 0.0; + binormals[31] = 0.0; + binormals[32] = 1.0; + binormals[33] = 0.0; + binormals[34] = 0.0; + binormals[35] = 1.0; // -x face - binormals[36] = 0.0; binormals[37] = 0.0; binormals[38] = 1.0; - binormals[39] = 0.0; binormals[40] = 0.0; binormals[41] = 1.0; - binormals[42] = 0.0; binormals[43] = 0.0; binormals[44] = 1.0; - binormals[45] = 0.0; binormals[46] = 0.0; binormals[47] = 1.0; + binormals[36] = 0.0; + binormals[37] = 0.0; + binormals[38] = 1.0; + binormals[39] = 0.0; + binormals[40] = 0.0; + binormals[41] = 1.0; + binormals[42] = 0.0; + binormals[43] = 0.0; + binormals[44] = 1.0; + binormals[45] = 0.0; + binormals[46] = 0.0; + binormals[47] = 1.0; // +y face - binormals[48] = 0.0; binormals[49] = 0.0; binormals[50] = 1.0; - binormals[51] = 0.0; binormals[52] = 0.0; binormals[53] = 1.0; - binormals[54] = 0.0; binormals[55] = 0.0; binormals[56] = 1.0; - binormals[57] = 0.0; binormals[58] = 0.0; binormals[59] = 1.0; + binormals[48] = 0.0; + binormals[49] = 0.0; + binormals[50] = 1.0; + binormals[51] = 0.0; + binormals[52] = 0.0; + binormals[53] = 1.0; + binormals[54] = 0.0; + binormals[55] = 0.0; + binormals[56] = 1.0; + binormals[57] = 0.0; + binormals[58] = 0.0; + binormals[59] = 1.0; // -y face - binormals[60] = 0.0; binormals[61] = 0.0; binormals[62] = 1.0; - binormals[63] = 0.0; binormals[64] = 0.0; binormals[65] = 1.0; - binormals[66] = 0.0; binormals[67] = 0.0; binormals[68] = 1.0; - binormals[69] = 0.0; binormals[70] = 0.0; binormals[71] = 1.0; + binormals[60] = 0.0; + binormals[61] = 0.0; + binormals[62] = 1.0; + binormals[63] = 0.0; + binormals[64] = 0.0; + binormals[65] = 1.0; + binormals[66] = 0.0; + binormals[67] = 0.0; + binormals[68] = 1.0; + binormals[69] = 0.0; + binormals[70] = 0.0; + binormals[71] = 1.0; attributes.binormal = new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, @@ -302,40 +515,80 @@ define([ indices = new Uint16Array(6 * 2 * 3); // +z face - indices[0] = 0; indices[1] = 1; indices[2] = 2; - indices[3] = 0; indices[4] = 2; indices[5] = 3; + indices[0] = 0; + indices[1] = 1; + indices[2] = 2; + indices[3] = 0; + indices[4] = 2; + indices[5] = 3; // -z face - indices[6] = 4 + 2; indices[7] = 4 + 1; indices[8] = 4 + 0; - indices[9] = 4 + 3; indices[10] = 4 + 2; indices[11] = 4 + 0; + indices[6] = 4 + 2; + indices[7] = 4 + 1; + indices[8] = 4 + 0; + indices[9] = 4 + 3; + indices[10] = 4 + 2; + indices[11] = 4 + 0; // +x face - indices[12] = 8 + 0; indices[13] = 8 + 1; indices[14] = 8 + 2; - indices[15] = 8 + 0; indices[16] = 8 + 2; indices[17] = 8 + 3; + indices[12] = 8 + 0; + indices[13] = 8 + 1; + indices[14] = 8 + 2; + indices[15] = 8 + 0; + indices[16] = 8 + 2; + indices[17] = 8 + 3; // -x face - indices[18] = 12 + 2; indices[19] = 12 + 1; indices[20] = 12 + 0; - indices[21] = 12 + 3; indices[22] = 12 + 2; indices[23] = 12 + 0; + indices[18] = 12 + 2; + indices[19] = 12 + 1; + indices[20] = 12 + 0; + indices[21] = 12 + 3; + indices[22] = 12 + 2; + indices[23] = 12 + 0; // +y face - indices[24] = 16 + 2; indices[25] = 16 + 1; indices[26] = 16 + 0; - indices[27] = 16 + 3; indices[28] = 16 + 2; indices[29] = 16 + 0; + indices[24] = 16 + 2; + indices[25] = 16 + 1; + indices[26] = 16 + 0; + indices[27] = 16 + 3; + indices[28] = 16 + 2; + indices[29] = 16 + 0; // -y face - indices[30] = 20 + 0; indices[31] = 20 + 1; indices[32] = 20 + 2; - indices[33] = 20 + 0; indices[34] = 20 + 2; indices[35] = 20 + 3; + indices[30] = 20 + 0; + indices[31] = 20 + 1; + indices[32] = 20 + 2; + indices[33] = 20 + 0; + indices[34] = 20 + 2; + indices[35] = 20 + 3; } else { // Positions only - no need to duplicate corner points positions = new Float64Array(8 * 3); - positions[0] = min.x; positions[1] = min.y; positions[2] = min.z; - positions[3] = max.x; positions[4] = min.y; positions[5] = min.z; - positions[6] = max.x; positions[7] = max.y; positions[8] = min.z; - positions[9] = min.x; positions[10] = max.y; positions[11] = min.z; - positions[12] = min.x; positions[13] = min.y; positions[14] = max.z; - positions[15] = max.x; positions[16] = min.y; positions[17] = max.z; - positions[18] = max.x; positions[19] = max.y; positions[20] = max.z; - positions[21] = min.x; positions[22] = max.y; positions[23] = max.z; + positions[0] = min.x; + positions[1] = min.y; + positions[2] = min.z; + positions[3] = max.x; + positions[4] = min.y; + positions[5] = min.z; + positions[6] = max.x; + positions[7] = max.y; + positions[8] = min.z; + positions[9] = min.x; + positions[10] = max.y; + positions[11] = min.z; + positions[12] = min.x; + positions[13] = min.y; + positions[14] = max.z; + positions[15] = max.x; + positions[16] = min.y; + positions[17] = max.z; + positions[18] = max.x; + positions[19] = max.y; + positions[20] = max.z; + positions[21] = min.x; + positions[22] = max.y; + positions[23] = max.z; attributes.position = new GeometryAttribute({ componentDatatype : ComponentDatatype.DOUBLE, @@ -347,42 +600,69 @@ define([ indices = new Uint16Array(6 * 2 * 3); // plane z = corner.Z - indices[0] = 4; indices[1] = 5; indices[2] = 6; - indices[3] = 4; indices[4] = 6; indices[5] = 7; + indices[0] = 4; + indices[1] = 5; + indices[2] = 6; + indices[3] = 4; + indices[4] = 6; + indices[5] = 7; // plane z = -corner.Z - indices[6] = 1; indices[7] = 0; indices[8] = 3; - indices[9] = 1; indices[10] = 3; indices[11] = 2; + indices[6] = 1; + indices[7] = 0; + indices[8] = 3; + indices[9] = 1; + indices[10] = 3; + indices[11] = 2; // plane x = corner.X - indices[12] = 1; indices[13] = 6; indices[14] = 5; - indices[15] = 1; indices[16] = 2; indices[17] = 6; + indices[12] = 1; + indices[13] = 6; + indices[14] = 5; + indices[15] = 1; + indices[16] = 2; + indices[17] = 6; // plane y = corner.Y - indices[18] = 2; indices[19] = 3; indices[20] = 7; - indices[21] = 2; indices[22] = 7; indices[23] = 6; + indices[18] = 2; + indices[19] = 3; + indices[20] = 7; + indices[21] = 2; + indices[22] = 7; + indices[23] = 6; // plane x = -corner.X - indices[24] = 3; indices[25] = 0; indices[26] = 4; - indices[27] = 3; indices[28] = 4; indices[29] = 7; + indices[24] = 3; + indices[25] = 0; + indices[26] = 4; + indices[27] = 3; + indices[28] = 4; + indices[29] = 7; // plane y = -corner.Y - indices[30] = 0; indices[31] = 1; indices[32] = 5; - indices[33] = 0; indices[34] = 5; indices[35] = 4; + indices[30] = 0; + indices[31] = 1; + indices[32] = 5; + indices[33] = 0; + indices[34] = 5; + indices[35] = 4; } + var diff = Cartesian3.subtract(max, min, diffScratch); + var radius = diff.magnitude() * 0.5; + /** * An object containing {@link GeometryAttribute} properties named after each of the * true values of the {@link VertexFormat} option. * - * @type Object + * @type GeometryAttributes * * @see Geometry#attributes */ this.attributes = attributes; /** - * Index data that - along with {@link Geometry#primitiveType} - determines the primitives in the geometry. + * Index data that, along with {@link Geometry#primitiveType}, determines the primitives in the geometry. * * @type Array */ @@ -400,7 +680,47 @@ define([ * * @type BoundingSphere */ - this.boundingSphere = new BoundingSphere(new Cartesian3(), max.subtract(min).magnitude() * 0.5); + this.boundingSphere = new BoundingSphere(Cartesian3.ZERO, radius); + }; + + /** + * Creates vertices and indices for a cube centered at the origin given its dimensions. + * @memberof BoxGeometry + * + * @param {Cartesian3} options.dimensions The width, depth, and height of the box stored in the x, y, and z coordinates of the Cartesian3, respectively. + * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed. + * + * @exception {DeveloperError} options.dimensions is required. + * @exception {DeveloperError} All dimensions components must be greater than or equal to zero. + * + * @example + * var box = BoxGeometry.fromDimensions({ + * vertexFormat : VertexFormat.POSITION_ONLY, + * dimensions : new Cartesian3(500000.0, 500000.0, 500000.0) + * }); + */ + BoxGeometry.fromDimensions = function(options) { + options = defaultValue(options, defaultValue.EMPTY_OBJECT); + + var dimensions = options.dimensions; + if (typeof dimensions === 'undefined') { + throw new DeveloperError('options.dimensions is required.'); + } + + if (dimensions.x < 0 || dimensions.y < 0 || dimensions.z < 0) { + throw new DeveloperError('All dimensions components must be greater than or equal to zero.'); + } + + var corner = dimensions.multiplyByScalar(0.5); + var min = corner.negate(); + var max = corner; + + var newOptions = { + minimumCorner : min, + maximumCorner : max, + vertexFormat : options.vertexFormat + }; + return new BoxGeometry(newOptions); }; return BoxGeometry; diff --git a/Source/Core/CircleGeometry.js b/Source/Core/CircleGeometry.js index e9b6ef05f3ef..4e8f39878850 100644 --- a/Source/Core/CircleGeometry.js +++ b/Source/Core/CircleGeometry.js @@ -59,14 +59,14 @@ define([ * An object containing {@link GeometryAttribute} properties named after each of the * true values of the {@link VertexFormat} option. * - * @type Object + * @type GeometryAttributes * * @see Geometry#attributes */ this.attributes = ellipseGeometry.attributes; /** - * Index data that - along with {@link Geometry#primitiveType} - determines the primitives in the geometry. + * Index data that, along with {@link Geometry#primitiveType}, determines the primitives in the geometry. * * @type Array */ diff --git a/Source/Core/EllipseGeometry.js b/Source/Core/EllipseGeometry.js index 315e211ce56d..368254134751 100644 --- a/Source/Core/EllipseGeometry.js +++ b/Source/Core/EllipseGeometry.js @@ -8,6 +8,7 @@ define([ './DeveloperError', './Ellipsoid', './GeometryAttribute', + './GeometryAttributes', './Math', './Matrix3', './PrimitiveType', @@ -22,6 +23,7 @@ define([ DeveloperError, Ellipsoid, GeometryAttribute, + GeometryAttributes, CesiumMath, Matrix3, PrimitiveType, @@ -303,7 +305,7 @@ define([ } } - var attributes = {}; + var attributes = new GeometryAttributes(); if (vertexFormat.position) { attributes.position = new GeometryAttribute({ @@ -430,14 +432,14 @@ define([ * An object containing {@link GeometryAttribute} properties named after each of the * true values of the {@link VertexFormat} option. * - * @type Object + * @type GeometryAttributes * * @see Geometry#attributes */ this.attributes = attributes; /** - * Index data that - along with {@link Geometry#primitiveType} - determines the primitives in the geometry. + * Index data that, along with {@link Geometry#primitiveType}, determines the primitives in the geometry. * * @type Array */ diff --git a/Source/Core/EllipsoidGeometry.js b/Source/Core/EllipsoidGeometry.js index ee9a0090a5b4..f4b777f52f54 100644 --- a/Source/Core/EllipsoidGeometry.js +++ b/Source/Core/EllipsoidGeometry.js @@ -10,6 +10,7 @@ define([ './PrimitiveType', './BoundingSphere', './GeometryAttribute', + './GeometryAttributes', './VertexFormat' ], function( defaultValue, @@ -22,6 +23,7 @@ define([ PrimitiveType, BoundingSphere, GeometryAttribute, + GeometryAttributes, VertexFormat) { "use strict"; @@ -127,8 +129,7 @@ define([ * @example * var ellipsoid = new EllipsoidGeometry({ * vertexFormat : VertexFormat.POSITION_ONLY, - * ellipsoid : new Ellipsoid(1000000.0, 500000.0, 500000.0), - * modelMatrix : Transforms.eastNorthUpToFixedFrame(center) + * ellipsoid : new Ellipsoid(1000000.0, 500000.0, 500000.0) * }); */ var EllipsoidGeometry = function(options) { @@ -204,7 +205,7 @@ define([ // Plane z = -1 addFaceTriangles(edge1to2, edge0to1.slice(0).reverse(), edge3to0.slice(0).reverse(), edge2to3, numberOfPartitions, positions, indices); - var attributes = {}; + var attributes = new GeometryAttributes(); var length = positions.length; var i; @@ -316,7 +317,7 @@ define([ this.attributes = attributes; /** - * Index data that - along with {@link Geometry#primitiveType} - determines the primitives in the geometry. + * Index data that, along with {@link Geometry#primitiveType}, determines the primitives in the geometry. * * @type Array */ diff --git a/Source/Core/ExtentGeometry.js b/Source/Core/ExtentGeometry.js index fa82b9b84963..51b901794000 100644 --- a/Source/Core/ExtentGeometry.js +++ b/Source/Core/ExtentGeometry.js @@ -12,6 +12,7 @@ define([ './Extent', './GeographicProjection', './GeometryAttribute', + './GeometryAttributes', './Math', './Matrix2', './PrimitiveType', @@ -29,6 +30,7 @@ define([ Extent, GeographicProjection, GeometryAttribute, + GeometryAttributes, CesiumMath, Matrix2, PrimitiveType, @@ -147,7 +149,7 @@ define([ } var vertexFormat = defaultValue(options.vertexFormat, VertexFormat.DEFAULT); - var attributes = {}; + var attributes = new GeometryAttributes(); var positionIndex = 0; var stIndex = 0; @@ -295,14 +297,14 @@ define([ * An object containing {@link GeometryAttribute} properties named after each of the * true values of the {@link VertexFormat} option. * - * @type Object + * @type GeometryAttributes * * @see Geometry#attributes */ this.attributes = attributes; /** - * Index data that - along with {@link Geometry#primitiveType} - determines the primitives in the geometry. + * Index data that, along with {@link Geometry#primitiveType}, determines the primitives in the geometry. * * @type Array */ diff --git a/Source/Core/Geometry.js b/Source/Core/Geometry.js index 51287aea21db..bb2e7d298f5f 100644 --- a/Source/Core/Geometry.js +++ b/Source/Core/Geometry.js @@ -93,7 +93,7 @@ define([ * *

    * - * @type Object + * @type GeometryAttributes * * @default undefined * @@ -178,7 +178,7 @@ define([ var attributes = geometry.attributes; var newAttributes = {}; for (var property in attributes) { - if (attributes.hasOwnProperty(property)) { + if (attributes.hasOwnProperty(property) && typeof attributes[property] !== 'undefined') { newAttributes[property] = attributes[property].clone(); } } @@ -218,7 +218,10 @@ define([ var numberOfVertices = -1; for ( var property in geometry.attributes) { - if (geometry.attributes.hasOwnProperty(property) && geometry.attributes[property].values) { + if (geometry.attributes.hasOwnProperty(property) && + typeof geometry.attributes[property] !== 'undefined' && + typeof geometry.attributes[property].values !== 'undefined') { + var attribute = geometry.attributes[property]; var num = attribute.values.length / attribute.componentsPerAttribute; if ((numberOfVertices !== num) && (numberOfVertices !== -1)) { diff --git a/Source/Core/GeometryAttributes.js b/Source/Core/GeometryAttributes.js new file mode 100644 index 000000000000..a2670915c22d --- /dev/null +++ b/Source/Core/GeometryAttributes.js @@ -0,0 +1,82 @@ +/*global define*/ +define(['./defaultValue'], function(defaultValue) { + "use strict"; + + /** + * Attributes, which make up a geometry's vertices. Each property in this object corresponds to a + * {@link GeometryAttribute} containing the attribute's data. + *

    + * Attributes are always stored non-interleaved in a Geometry. When geometry is prepared for rendering + * with {@link Context#createVertexArrayFromGeometry}, attributes are generally written interleaved + * into the vertex buffer for better rendering performance. + *

    + * + * @alias VertexFormat + * @constructor + */ + var GeometryAttributes = function(options) { + options = defaultValue(options, defaultValue.EMPTY_OBJECT); + + /** + * The 3D position attribute. + *

    + * 64-bit floating-point (for precision). 3 components per attribute. + *

    + * + * @type GeometryAttribute + * + * @default undefined + */ + this.position = options.position; + + /** + * The normal attribute (normalized), which is commonly used for lighting. + *

    + * 32-bit floating-point. 3 components per attribute. + *

    + * + * @type GeometryAttribute + * + * @default undefined + */ + this.normal = options.normal; + + /** + * The 2D texture coordinate attribute. + *

    + * 32-bit floating-point. 2 components per attribute + *

    + * + * @type GeometryAttribute + * + * @default undefined + */ + this.st = options.st; + + /** + * The binormal attribute (normalized), which is used for tangent-space effects like bump mapping. + *

    + * 32-bit floating-point. 3 components per attribute. + *

    + * + * @type GeometryAttribute + * + * @default undefined + */ + this.binormal = options.binormal; + + /** + * The tangent attribute (normalized), which is used for tangent-space effects like bump mapping. + *

    + * 32-bit floating-point. 3 components per attribute. + *

    + * + * @type GeometryAttribute + * + * @default undefined + */ + this.tangent = options.tangent; + }; + + return GeometryAttributes; +}); \ No newline at end of file diff --git a/Source/Core/PolygonGeometry.js b/Source/Core/PolygonGeometry.js index 0f59f3f83d2a..69383d6d7f10 100644 --- a/Source/Core/PolygonGeometry.js +++ b/Source/Core/PolygonGeometry.js @@ -11,6 +11,7 @@ define([ './Ellipsoid', './EllipsoidTangentPlane', './GeometryAttribute', + './GeometryAttributes', './GeometryInstance', './GeometryPipeline', './IndexDatatype', @@ -34,6 +35,7 @@ define([ Ellipsoid, EllipsoidTangentPlane, GeometryAttribute, + GeometryAttributes, GeometryInstance, GeometryPipeline, IndexDatatype, @@ -279,7 +281,7 @@ define([ ellipsoid.geodeticSurfaceNormal(center, center); Cartesian3.multiplyByScalar(center, mag + height, center); - var attributes = {}; + var attributes = new GeometryAttributes(); if (vertexFormat.position) { attributes.position = new GeometryAttribute({ @@ -409,14 +411,14 @@ define([ * An object containing {@link GeometryAttribute} properties named after each of the * true values of the {@link VertexFormat} option. * - * @type Object + * @type GeometryAttributes * * @see Geometry#attributes */ this.attributes = attributes; /** - * Index data that - along with {@link Geometry#primitiveType} - determines the primitives in the geometry. + * Index data that, along with {@link Geometry#primitiveType}, determines the primitives in the geometry. * * @type Array */ diff --git a/Source/Core/SimplePolylineGeometry.js b/Source/Core/SimplePolylineGeometry.js index d60284608112..82a39e8ed08f 100644 --- a/Source/Core/SimplePolylineGeometry.js +++ b/Source/Core/SimplePolylineGeometry.js @@ -6,7 +6,8 @@ define([ './PrimitiveType', './defaultValue', './BoundingSphere', - './GeometryAttribute' + './GeometryAttribute', + './GeometryAttributes' ], function( DeveloperError, ComponentDatatype, @@ -14,7 +15,8 @@ define([ PrimitiveType, defaultValue, BoundingSphere, - GeometryAttribute) { + GeometryAttribute, + GeometryAttributes) { "use strict"; /** @@ -59,13 +61,12 @@ define([ positionValues[j++] = p.z; } - var attributes = { - position : new GeometryAttribute({ - componentDatatype : ComponentDatatype.DOUBLE, - componentsPerAttribute : 3, - values : positionValues - }) - }; + var attributes = new GeometryAttributes(); + attributes.position = new GeometryAttribute({ + componentDatatype : ComponentDatatype.DOUBLE, + componentsPerAttribute : 3, + values : positionValues + }); // From line strip to lines var numberOfIndices = 2 * (numberOfPositions - 1); @@ -88,7 +89,7 @@ define([ this.attributes = attributes; /** - * Index data that - along with {@link Geometry#primitiveType} - determines the primitives in the geometry. + * Index data that, along with {@link Geometry#primitiveType}, determines the primitives in the geometry. * * @type Array */ diff --git a/Source/Core/WallGeometry.js b/Source/Core/WallGeometry.js index 14c298d28532..d4ecd1098963 100644 --- a/Source/Core/WallGeometry.js +++ b/Source/Core/WallGeometry.js @@ -10,6 +10,7 @@ define([ './Ellipsoid', './EllipsoidTangentPlane', './GeometryAttribute', + './GeometryAttributes', './Math', './PolylinePipeline', './PolygonPipeline', @@ -27,6 +28,7 @@ define([ Ellipsoid, EllipsoidTangentPlane, GeometryAttribute, + GeometryAttributes, CesiumMath, PolylinePipeline, PolygonPipeline, @@ -239,7 +241,7 @@ define([ } } - var attributes = {}; + var attributes = new GeometryAttributes(); if (vertexFormat.position) { attributes.position = new GeometryAttribute({ @@ -324,14 +326,14 @@ define([ * An object containing {@link GeometryAttribute} properties named after each of the * true values of the {@link VertexFormat} option. * - * @type Object + * @type GeometryAttributes * * @see Geometry#attributes */ this.attributes = attributes; /** - * Index data that - along with {@link Geometry#primitiveType} - determines the primitives in the geometry. + * Index data that, along with {@link Geometry#primitiveType}, determines the primitives in the geometry. * * @type Array */ diff --git a/Source/Renderer/Context.js b/Source/Renderer/Context.js index 47d02e65423e..186699be8a1d 100644 --- a/Source/Renderer/Context.js +++ b/Source/Renderer/Context.js @@ -2418,7 +2418,7 @@ define([ } else { // One vertex buffer per attribute. for (name in attributes) { - if (attributes.hasOwnProperty(name)) { + if (attributes.hasOwnProperty(name) && typeof attributes[name] !== 'undefined') { attribute = attributes[name]; var componentDatatype = attribute.componentDatatype; diff --git a/Source/Scene/SkyBox.js b/Source/Scene/SkyBox.js index abbd6f2fd600..7c7e4945cfeb 100644 --- a/Source/Scene/SkyBox.js +++ b/Source/Scene/SkyBox.js @@ -148,7 +148,7 @@ define([ } }; - var geometry = new BoxGeometry({ + var geometry = BoxGeometry.fromDimensions({ dimensions : new Cartesian3(2.0, 2.0, 2.0), vertexFormat : VertexFormat.POSITION_ONLY }); diff --git a/Specs/Core/BoundingSphereSpec.js b/Specs/Core/BoundingSphereSpec.js index fadf7f21a41d..4db94cf3d270 100644 --- a/Specs/Core/BoundingSphereSpec.js +++ b/Specs/Core/BoundingSphereSpec.js @@ -333,7 +333,7 @@ defineSuite([ it('fromEllipsoid with a result parameter', function() { var ellipsoid = Ellipsoid.WGS84; - var sphere = new BoundingSphere(); + var sphere = new BoundingSphere(new Cartesian3(1.0, 2.0, 3.0), 4.0); var result = BoundingSphere.fromEllipsoid(ellipsoid, sphere); expect(result).toBe(sphere); expect(result).toEqual(new BoundingSphere(Cartesian3.ZERO, ellipsoid.getMaximumRadius())); diff --git a/Specs/Core/BoxGeometrySpec.js b/Specs/Core/BoxGeometrySpec.js index 33df211eb5e0..ac371e996373 100644 --- a/Specs/Core/BoxGeometrySpec.js +++ b/Specs/Core/BoxGeometrySpec.js @@ -10,17 +10,26 @@ defineSuite([ "use strict"; /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/ - it('constructor throws with negative dimensions', function() { + it('constructor throws without minimum corner', function() { expect(function() { return new BoxGeometry({ - dimensions : new Cartesian3(1, 2, -1) + maximumCorner : new Cartesian3() + }); + }).toThrow(); + }); + + it('constructor throws without maximum corner', function() { + expect(function() { + return new BoxGeometry({ + minimumCorner : new Cartesian3() }); }).toThrow(); }); it('constructor creates optimized number of positions for VertexFormat.POSITIONS_ONLY', function() { var m = new BoxGeometry({ - dimensions : new Cartesian3(1, 2, 3), + minimumCorner : new Cartesian3(-1, -2, -3), + maximumCorner : new Cartesian3(1, 2, 3), vertexFormat : VertexFormat.POSITION_ONLY }); @@ -48,4 +57,28 @@ defineSuite([ expect(m.boundingSphere.center).toEqual(Cartesian3.ZERO); expect(m.boundingSphere.radius).toEqual(maximumCorner.magnitude() * 0.5); }); + + it('fromDimensions throws without dimensions', function() { + expect(function() { + return BoxGeometry.fromDimensions(); + }).toThrow(); + }); + + it('fromDimensions throws with negative dimensions', function() { + expect(function() { + return BoxGeometry.fromDimensions({ + dimensions : new Cartesian3(1, 2, -1) + }); + }).toThrow(); + }); + + it('fromDimensions', function() { + var m = BoxGeometry.fromDimensions({ + dimensions : new Cartesian3(1, 2, 3), + vertexFormat : VertexFormat.POSITION_ONLY + }); + + expect(m.attributes.position.values.length).toEqual(8 * 3); + expect(m.indices.length).toEqual(12 * 3); + }); }); \ No newline at end of file diff --git a/Specs/Scene/GeometryRenderingSpec.js b/Specs/Scene/GeometryRenderingSpec.js index 97e820e8cf82..2617f6d0e2c2 100644 --- a/Specs/Scene/GeometryRenderingSpec.js +++ b/Specs/Scene/GeometryRenderingSpec.js @@ -270,7 +270,7 @@ defineSuite([ var instance; beforeAll(function() { instance = new GeometryInstance({ - geometry : new BoxGeometry({ + geometry : BoxGeometry.fromDimensions({ vertexFormat : PerInstanceColorAppearance.FLAT_VERTEX_FORMAT, dimensions : new Cartesian3(1000000.0, 1000000.0, 2000000.0) }), From 4235b4ab91e00b1463da94fde70594dc0079041a Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 8 Jul 2013 21:25:30 -0400 Subject: [PATCH 295/306] More updates based on review. --- Source/Core/BoxGeometry.js | 2 +- Source/Core/CircleGeometry.js | 14 ++++++++---- Source/Core/ColorGeometryInstanceAttribute.js | 7 ++++-- Source/Core/EllipseGeometry.js | 22 +++++++++++-------- Source/Core/EllipsoidGeometry.js | 2 +- Source/Core/ExtentGeometry.js | 2 +- Source/Core/PolygonGeometry.js | 2 +- Source/Core/SimplePolylineGeometry.js | 2 +- Source/Core/WallGeometry.js | 2 +- Source/Scene/EllipsoidPrimitive.js | 2 +- Specs/Core/EllipseGeometrySpec.js | 10 +++++++++ 11 files changed, 45 insertions(+), 22 deletions(-) diff --git a/Source/Core/BoxGeometry.js b/Source/Core/BoxGeometry.js index 58198e971045..669b4f75adeb 100644 --- a/Source/Core/BoxGeometry.js +++ b/Source/Core/BoxGeometry.js @@ -24,7 +24,7 @@ define([ var diffScratch = new Cartesian3(); /** - * Creates vertices and indices for a cube centered at the origin. + * A {@link Geometry} that represents vertices and indices for a cube centered at the origin. * * @alias BoxGeometry * @constructor diff --git a/Source/Core/CircleGeometry.js b/Source/Core/CircleGeometry.js index 4e8f39878850..53a139a17d32 100644 --- a/Source/Core/CircleGeometry.js +++ b/Source/Core/CircleGeometry.js @@ -12,7 +12,7 @@ define([ "use strict"; /** - * Computes vertices and indices for a circle on the ellipsoid. + * A {@link Geometry} that represents vertices and indices for a circle on the ellipsoid. * * @alias CircleGeometry * @constructor @@ -50,9 +50,15 @@ define([ throw new DeveloperError('radius must be greater than zero.'); } - var ellipseGeometryOptions = clone(options); - ellipseGeometryOptions.semiMajorAxis = radius; - ellipseGeometryOptions.semiMinorAxis = radius; + var ellipseGeometryOptions = { + center : options.center, + semiMajorAxis : radius, + semiMinorAxis : radius, + ellipsoid : options.ellipsoid, + height : options.height, + granularity : options.granularity, + vertexFormat : options.vertexFormat + }; var ellipseGeometry = new EllipseGeometry(ellipseGeometryOptions); /** diff --git a/Source/Core/ColorGeometryInstanceAttribute.js b/Source/Core/ColorGeometryInstanceAttribute.js index 935a5b442331..76b68dff32e9 100644 --- a/Source/Core/ColorGeometryInstanceAttribute.js +++ b/Source/Core/ColorGeometryInstanceAttribute.js @@ -17,7 +17,10 @@ define([ * @alias ColorGeometryInstanceAttribute * @constructor * - * @param {Color} [color=new Color(1.0, 0.0, 0.0, 0.5)] The color of the geometry instance. + * @param {Number} [red=1.0] The red component. + * @param {Number} [green=1.0] The green component. + * @param {Number} [blue=1.0] The blue component. + * @param {Number} [alpha=1.0] The alpha component. * * @example * var instance = new GeometryInstance({ @@ -82,7 +85,7 @@ define([ * * @type Uint8Array * - * @default [1.0, 0.0, 0.0, 0.5] + * @default [255, 255, 255, 255] */ this.value = new Uint8Array([ Color.floatToByte(red), diff --git a/Source/Core/EllipseGeometry.js b/Source/Core/EllipseGeometry.js index 368254134751..d75ff820f593 100644 --- a/Source/Core/EllipseGeometry.js +++ b/Source/Core/EllipseGeometry.js @@ -66,9 +66,12 @@ define([ var scratchCartesian2 = new Cartesian3(); var scratchCartesian3 = new Cartesian3(); var scratchCartesian4 = new Cartesian3(); + var unitPosScratch = new Cartesian3(); + var eastVecScratch = new Cartesian3(); + var northVecScratch = new Cartesian3(); /** - * Computes vertices and indices for an ellipse on the ellipsoid. + * A {@link Geometry} that represents vertices and indices for an ellipse on the ellipsoid. * * @alias EllipseGeometry * @constructor @@ -86,6 +89,7 @@ define([ * @exception {DeveloperError} semiMajorAxis is required. * @exception {DeveloperError} semiMinorAxis is required. * @exception {DeveloperError} semiMajorAxis and semiMinorAxis must be greater than zero. + * @exception {DeveloperError} semiMajorAxis must be larger than the semiMajorAxis. * @exception {DeveloperError} granularity must be greater than zero. * * @example @@ -131,9 +135,7 @@ define([ } if (semiMajorAxis < semiMinorAxis) { - var temp = semiMajorAxis; - semiMajorAxis = semiMinorAxis; - semiMinorAxis = temp; + throw new DeveloperError('semiMajorAxis must be larger than the semiMajorAxis.'); } var vertexFormat = defaultValue(options.vertexFormat, VertexFormat.DEFAULT); @@ -146,10 +148,10 @@ define([ var mag = center.magnitude(); - var unitPos = Cartesian3.normalize(center); - var eastVec = Cartesian3.cross(Cartesian3.UNIT_Z, center); + var unitPos = Cartesian3.normalize(center, unitPosScratch); + var eastVec = Cartesian3.cross(Cartesian3.UNIT_Z, center, eastVecScratch); Cartesian3.normalize(eastVec, eastVec); - var northVec = Cartesian3.cross(unitPos, eastVec); + var northVec = Cartesian3.cross(unitPos, eastVec, northVecScratch); // The number of points in the first quadrant var numPts = 1 + Math.ceil(CesiumMath.PI_OVER_TWO / granularity); @@ -181,13 +183,13 @@ define([ var i; var j; - var theta; var numInterior; var t; var interiorPosition; // Compute points in the 'northern' half of the ellipse - for (i = 0, theta = CesiumMath.PI_OVER_TWO; i < numPts && theta > 0; ++i, theta -= deltaTheta) { + var theta = CesiumMath.PI_OVER_TWO; + for (i = 0; i < numPts && theta > 0; ++i) { pointOnEllipsoid(theta, bearing, northVec, eastVec, aSqr, ab, bSqr, mag, unitPos, position); pointOnEllipsoid(Math.PI - theta, bearing, northVec, eastVec, aSqr, ab, bSqr, mag, unitPos, reflectedPosition); @@ -207,6 +209,8 @@ define([ positions[positionIndex++] = reflectedPosition.x; positions[positionIndex++] = reflectedPosition.y; positions[positionIndex++] = reflectedPosition.z; + + theta = CesiumMath.PI_OVER_TWO - (i + 1) * deltaTheta; } // Set numPts if theta reached zero diff --git a/Source/Core/EllipsoidGeometry.js b/Source/Core/EllipsoidGeometry.js index f4b777f52f54..10718751d342 100644 --- a/Source/Core/EllipsoidGeometry.js +++ b/Source/Core/EllipsoidGeometry.js @@ -115,7 +115,7 @@ define([ var binormal = new Cartesian3(); /** - * Creates vertices and indices for an ellipsoid centered at the origin. + * A {@link Geometry} that represents vertices and indices for an ellipsoid centered at the origin. * * @alias EllipsoidGeometry * @constructor diff --git a/Source/Core/ExtentGeometry.js b/Source/Core/ExtentGeometry.js index 51b901794000..082611fed15d 100644 --- a/Source/Core/ExtentGeometry.js +++ b/Source/Core/ExtentGeometry.js @@ -59,7 +59,7 @@ define([ var binormal = new Cartesian3(); /** - * Creates geometry for a cartographic extent on an ellipsoid centered at the origin. + * A {@link Geometry} that represents geometry for a cartographic extent on an ellipsoid centered at the origin. * * @alias ExtentGeometry * @constructor diff --git a/Source/Core/PolygonGeometry.js b/Source/Core/PolygonGeometry.js index 69383d6d7f10..a9e5f07fc807 100644 --- a/Source/Core/PolygonGeometry.js +++ b/Source/Core/PolygonGeometry.js @@ -121,7 +121,7 @@ define([ var appendTextureCoordinatesMatrix3 = new Matrix3(); /** - * Computes vertices and indices for a polygon on the ellipsoid. The polygon is either defined + * A {@link Geometry} that represents vertices and indices for a polygon on the ellipsoid. The polygon is either defined * by an array of Cartesian points, or a polygon hierarchy. * * @alias PolygonGeometry diff --git a/Source/Core/SimplePolylineGeometry.js b/Source/Core/SimplePolylineGeometry.js index 82a39e8ed08f..fa7d8718a07f 100644 --- a/Source/Core/SimplePolylineGeometry.js +++ b/Source/Core/SimplePolylineGeometry.js @@ -20,7 +20,7 @@ define([ "use strict"; /** - * A polyline modeled as a line strip; the first two positions define a line segment, + * A {@link Geometry} that represents a polyline modeled as a line strip; the first two positions define a line segment, * and each additional position defines a line segment from the previous position. * * @alias SimplePolylineGeometry diff --git a/Source/Core/WallGeometry.js b/Source/Core/WallGeometry.js index d4ecd1098963..51611e64b60b 100644 --- a/Source/Core/WallGeometry.js +++ b/Source/Core/WallGeometry.js @@ -46,7 +46,7 @@ define([ var scratchNormal = new Cartesian3(); /** - * Creates a wall, which is similar to a KML line string. A wall is defined by a series of points, + * A {@link Geometry} that represents a wall, which is similar to a KML line string. A wall is defined by a series of points, * which extrude down to the ground. Optionally, they can extrude downwards to a specified height. * The points in the wall can be offset by supplied terrain elevation data. * diff --git a/Source/Scene/EllipsoidPrimitive.js b/Source/Scene/EllipsoidPrimitive.js index cc07fe862835..a4644e5c275a 100644 --- a/Source/Scene/EllipsoidPrimitive.js +++ b/Source/Scene/EllipsoidPrimitive.js @@ -197,7 +197,7 @@ define([ return vertexArray; } - var geometry = new BoxGeometry({ + var geometry = BoxGeometry.fromDimensions({ dimensions : new Cartesian3(2.0, 2.0, 2.0) }); diff --git a/Specs/Core/EllipseGeometrySpec.js b/Specs/Core/EllipseGeometrySpec.js index 596c3ab78749..13ac2d333fd6 100644 --- a/Specs/Core/EllipseGeometrySpec.js +++ b/Specs/Core/EllipseGeometrySpec.js @@ -62,6 +62,16 @@ defineSuite([ }).toThrow(); }); + it('throws when semiMajorAxis is less than the semiMajorAxis', function() { + expect(function() { + return new EllipseGeometry({ + center : Ellipsoid.WGS84.cartographicToCartesian(new Cartographic()), + semiMajorAxis : 1.0, + semiMinorAxis : 2.0 + }); + }).toThrow(); + }); + it('computes positions', function() { var ellipsoid = Ellipsoid.WGS84; var m = new EllipseGeometry({ From ba7a1d317f19c79f9cdf89be34dbd210be4a4160 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Tue, 9 Jul 2013 17:07:12 -0400 Subject: [PATCH 296/306] More updates after review. --- Apps/Sandcastle/gallery/Custom Rendering.html | 93 ----------- Apps/Sandcastle/gallery/Custom Rendering.jpg | Bin 13145 -> 0 bytes Source/Core/EllipseGeometry.js | 18 +-- Source/Core/EllipsoidGeometry.js | 13 +- Source/Core/Extent.js | 16 +- Source/Core/ExtentGeometry.js | 4 +- Source/Core/Geometry.js | 75 ++------- Source/Core/GeometryAttribute.js | 49 +++--- Source/Core/GeometryInstance.js | 47 ++---- Source/Core/GeometryInstanceAttribute.js | 42 ++--- Source/Core/GeometryPipeline.js | 13 +- Source/Core/PolygonGeometry.js | 4 +- Source/Core/PolygonPipeline.js | 2 +- Source/Core/Shapes.js | 4 +- Source/Renderer/Context.js | 6 +- Source/Scene/CentralBodySurface.js | 2 +- Source/Scene/ExtentPrimitive.js | 6 +- Source/Scene/Polygon.js | 4 +- Source/Scene/Primitive.js | 68 ++++++++- Source/Scene/SkyAtmosphere.js | 2 +- Source/Scene/SunPostProcess.js | 3 +- Source/Scene/ViewportQuad.js | 3 +- Specs/Core/EllipsoidGeometrySpec.js | 3 - Specs/Core/GeometryAttributeSpec.js | 89 ++++++----- Specs/Core/GeometryInstanceAttributeSpec.js | 61 ++++---- Specs/Core/GeometryInstanceSpec.js | 97 +----------- Specs/Core/GeometryPipelineSpec.js | 144 +++++++++++------- Specs/Core/GeometrySpec.js | 143 ++--------------- Specs/Renderer/VertexArrayFactorySpec.js | 34 +++-- Specs/Scene/ExtentPrimitiveSpec.js | 2 +- Specs/Scene/GeometryRenderingSpec.js | 2 +- Specs/Scene/PolygonSpec.js | 2 +- .../createTangentSpaceDebugPrimitiveSpec.js | 2 +- 33 files changed, 405 insertions(+), 648 deletions(-) delete mode 100644 Apps/Sandcastle/gallery/Custom Rendering.html delete mode 100644 Apps/Sandcastle/gallery/Custom Rendering.jpg diff --git a/Apps/Sandcastle/gallery/Custom Rendering.html b/Apps/Sandcastle/gallery/Custom Rendering.html deleted file mode 100644 index f8a8e9f78f7e..000000000000 --- a/Apps/Sandcastle/gallery/Custom Rendering.html +++ /dev/null @@ -1,93 +0,0 @@ - - - - - - - - Cesium Demo - - - - - - - -
    -

    Loading...

    -
    - - - diff --git a/Apps/Sandcastle/gallery/Custom Rendering.jpg b/Apps/Sandcastle/gallery/Custom Rendering.jpg deleted file mode 100644 index 5595afcb61576e68f40a6e6ccee7b6e80f028a0e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13145 zcmbWdcT|(Xw=Nt6rAn3FrAn3FiGY-VfE4LPM5GA_(g{RSK)Qf{0)q5TKx*i{_ue5? zr6!aRAcPx#_pI}+b=LjkyLac^$-H@Ivi7rQvgeuEb31>#4xrT50BHd5@bCaHaWB9v z9N?tx@B9V;(A5P90000Y00ABo;4ZF&hf`%d=Kn5h;PC_S|MUGF+(R({?j1mlQ$3vi zlb1OC*XBQ;&+VMuy+!oYjX8WJM5IK-9s_Qd0BV3cczFM={}TMW`2XY{0RjG9!h3{- z|CETBl$eN!gou!kf?-CH; zY6s(<0|=<@Qge!_+@mqDBYf!jK>TAuHW8Oy$m3U))ipJl!KQB$X}dsDH6HFo_|#h85^BRIH3a*5 zcP~TeXnwksF6$1?B}Hi;);?GSxi9{fjD0jXYne%_9;Df=zrd`AppWsPpcp{PbiCV_ zxBR|aJ^iZX_ZxSTORq}`_r3OT(^KECDx>7CbovYUee{N5lfvHm4+tS5z=QjNea4AK z^?p=pf}nA>5_#jv4WY(7T78$Cv_`LHk*12*70u)FMiyqLOoI8ytd1;tjND5_6}T;x zQvksyNTIGf19=|(b0W4JSjoB5T)u_kSzcaKp%0pJ$};SMfyI~qqs#u=jV)QIr#D{| zb*}9xXmqppu#6LB%{*ihYeS{B!9TaCFT)H8I>ZO+7@3{g@rb!e;KQeiBDUcv63kL0 zp0!I0)_JX{Nt?Gtsz%@{Q^yzso10DO2R3>%u}i(h+GnhQe+A37sLd)X1t^sTQ_azI znu>R68iRom62?j00-T*CIZEOB_t4CpK}2?v^0uhtdAs-@j;+qC(*2|Mk76?CE69|+ zkqNu)M(?8+b&LAW({2Inq~4d_N!T{11R)%Er_T&Ft`35dqfKpQ4(wi5+bk`}Ro4&n zzRqH^vR8DNCs|{!Zix?{gG6CD{pnRX2Qi zXp2(jU+$8L1glrLo>*4&TRv}1*&VRLtMyB&u`_-N@eVWvT3(ZNLXiSRBIB`(w}AS5 z?^^)E;zr$HIQbR;-7o%|a@E&qO9Zf+z&LLP#e|znF&B9&yuOB+gtFIwIDj&Oo{ZOp ztm<+=mstBJ?TCtx>uY!Kc2GN8sOox`Nn?h5yd7a`$zucjdqJKy_Ui2O4bJ;tTJ(|i zJhy-kVAAaeqE1&%Z_#rbd|#BgU37vrgx{OaRZRGnErxBSiVGkfGY)XPlSR?)LlAnm z02&>{8Y)_!N&R6bmUz;`=V`)}w`V_+*(^GcLV8D8A54yhl0tRSI!&r*Jfx}V9Z%Gd zn?%>gudyGNZAgb@LQM7ClSi`b9_a{W5_4x8rKE$LhYYnT^g-gqpwnXCxufX=tgye! z(uQ*BCWJ7O3S)0^q>K zi*6gvNyS4tl&%Gk(oFHS;F2UHA$ShSH^7cKpTpC~F zyEs{7PL5GS5le&kIuzFrwJsl5DZ*IIpJ%J+ua`3nKz!XFHC*YKYvx}jpN9&RG=*pa z*T>>Qq|ooF;=8b-NaaYX=LHI^hC$vAtPe^m34*Ai{*E06Z?dYNmh*)*>oL~%FV2P6 zTo2^S_FDKxj4FC!t1nGcCv1A&X5m|eOqMgi{5(ys58q1}>O38L7QJcusn(xBeylT| z3_xSoFySMt+W9B*@Oq#y!mseCQi(!4X#_2{p*f_El<3&>)ru`^ek#5BYiwQ*v@0je z@_x2jQRZ6GzptA~GO)b&d)mE7exbBXm?vARGY7+1%4zbcp4P_Wkweq9&Ni~HjZN)HD&J2af^;?1k4U#2~ZS^E6;;VK_d538EwOX|;WekY+a+7Le;t?QDi zA;^iA0t&iM_h1ZNqzel>v2k)IOgzAqKH3$qT5}6xx676Wt$KysyRfK5Y{}mOA`2Q4 z^3&Y(c8#X$y10^3u9d1H-!1n^rrM)pJxzMvpuy@73Sf@h87};TR`uGtK~h8=1(Pj% zf&)&5#*2Z$YY2}kc0~hqTGZ}i1N8@h|EZ>B*kOy7y+7STQfFR%OT4wO#Z0$y9IlIkz2b^6XZx~0_ndMo7C>dkxP2FX#3 z^bsqtWd3yRAIly|ok_0PfF&Nmk9kg=nG8d&6d(j(f7{6F>MWXN%wu%4K(Z~R^PHjC z-;jrHgDc0B^JTtNPiH|jfn5c25JAYR7Q*&67U5$> zDQ7s4&B6*D-Dv{TdBo+zloe4g_G;Fv64a& z!4|ncli2Oa`p%71!P*xs%=PEf^*1ntUoQ}OosHgXzqmi7o42Y`VR1vfxY?he$=>7D zml*W2i@p6ma}PJ9QxM7C(U>>6-e+H`!~4ni*WvZCcj=ovYJbau>%3Wy9?_3}Huol8 zBFU42C?cC_A^hP}mNlwWJRFsEFtw4E{^y|B#`SNGR$_3$dg6!|kFKrmJ+x}cKhC=< zeh+oZ@;~hu@*%4M}P1>;mDu1{N;H{ z{$k9)>cv}s!42{j#FB-sPFLe<`L8{y;Gv)LM>@`_U;STmpjfX>-65{*l&&dQ{U~oJ zvHz-glZCabMkLfW=6w)R+`+}ZjG?}bYvJM><5qsvoTKzlm+Gf{r)ifY;~|>gO^b9G z$04uKtj3U@7n>l11+!1F^1b5t&Mf+^HMD8>DkThzy-=N=#f}17 zVl1sGByRykJNwhurlld{w*WFQJ^~1D>k1~comDg{vwsGgtXW0t9`=8;mAu#sqFk zzb^Ynkuk_QDyX$@P=JquEzW0v_H3iH@0D|T-D!~{o~b>^w16)f9|Ff z2bV5)F}AVTu%pE(3&2cuf|e@J0CR zSSe2G)xDDOJ(+QEs$uBF?;Kt>+Q?S-hITgmjV!voR@pgsDP32?wwZIm946PMrHIUc zFMvCvTUG0L1Ap#1rcU(Qi_gOY?DfR-=tItuK4*9vII9;j7ZeIg*03zwE4%%hQnUBj zDV6VI6mPP?Mj}5qfYf`dip{b14WU3XRiT=trGR_rZJq0HB5IsQCyT#N-r)?DwMV7G z5Wl}*XyI-5(fk63^uBey7e*fG3av9t8*`<3l83R5+?=EPxf>#FkpzqDk3~WI}8dL_MzpcqE zmDo}5#)Zm#4mEo%W@=0=C_Ws{8K$h-eXk|`z4Z2w2+PSmFCu>__Dpl71WP`53^vUL zznGB{{Ndrls`J#cv@}xBCgAm~H_Fd`IfXl`+!^C>3y8K{*Cm7x+wvS%ti133zW!6y zsV~`m?flTa<6VIHn+Dog#1DKl=|%t-4_Jbjt?%0L8T)LjGth%DK1k1d8rWWlz&^V8&h7_IYuSDR@~mNLUa5B0H0->(PM*qaGup**(^RDnz;(da2NAA99~7an2}= zDOj_kdf1_b1YUYqb#bxek)n}XVJ3L)n|I&q!Cvi*M~!76LO%3 zK5`}|ETKdMR8zEOWw61**>{s$#WP2FO}aiOfgo>RH*tx{F=I9Lz_Snu#O@&{v&trE zG~~Yjo}L|2xl`yowfBw-f18(yVtNfB-w%UmMpO2uH$N~>+Gw{Cvu*fJl+KlP*(EOG zc*3;>nHjZEDuR%JKrSb=UMR9RS#3`%(eUG<{+({L?{#;ztVwScv=fRr2 zZNGOzrB)0Np&mduKk{z$2&brIcVEGZM1ObU@T9f&`&+=A)G+21Iy{8WKaF^tOJvh;jZ`gy9ojHCUYP*}0rf3=8(H`EV6rsuI6(v0ILwxLhPTOMi2-+8ZUU$FPr=B5Chm z9KaBR=SO5vkD~oR3(dYG``EH0!1;E?mg3di_qj^ZkLOArD3vf8t?wf_{=KS>9PjE= zK%ZH5lU{)i+bix-gjpQyMl%w^qz<;`EmlYKl{I|~3-x!>6EWN|E;FIdb#)qSSw;GJ zYaKqWl67+?lR}jvG~fJx>b>|Dr$TUt=x@|nTgC)3I&}};G4C~agd0M-1R+HFNJ2fg> z0whhWRt#+UPmnnLPmmaCHkGIND2xjd#HnIyt8`0_PAc%vNp?R2zuRTRH(6vofV>ul zw6lq%O-`y$pQVS<%R5~44%VZ}^iz44!G-u_g~<*Micx#5qF|D_R(6aGZW`^n)&jty znU25A%ks5d{o5L9Wm|q&M7{4sW{8Vtc}BUtdH%mC zqkzWbW0L&HgL}FF9$IL=KZVJx)`?I7XCoa0?E=~r^>Xff$9m%Ty@Mi9#UNt{Z*{G# zw4D)+Hv5Bwof^C(TRk*0miV+}KQ8^yJ)duyB_#Q1jqDb%p3GEGFmW*X-Tmkx^j9as z-QLoanQIt|TT>kiW^t(HuAqld8XxV$O_Dm5gPt0YJXK0}B#gt-ZwW>841!h}WP z_gYF4eh(x8SAp=fo1ZtCkoB)ud9C-68cEVwqRFKTs>p0B(VzFb-5IXG#H>TwY^D%R zSRxO_90}oYLRQ22!3OdN0;YvgB{|=Yk|!rYptg+VHky%cq_u+jRP0e3bR5Hl<0B5D zlzYRl*g2&XaaR~(?SQo0CEriQ_Y&222K|!-AHz`5=>IkwMkU0T%#}H>A)e_+w2_rR zy*kH6-Ko&Kr}I@#NpK;+lpJ1LZh>R?JvXrLvy-uW7wn_J&u#19E$T`i z-ksb{$cVWU)17v;-+2qDbT5S4hWTcZp1aYVcFVIpTP%%a6p{Qpuv}?A&~KIvuI^Qd zGq+HSPmv=$&|heCqzI+4w6gK<>N=DV9B`j?nfv_hRUY(Pc_^b6!Dd3o2JBD`g}6xr zlUGG6h*Iv8J+E`CNnpw)k6Lx*+?~d^Rf_FJ6bR(RWRH-z?=8wm`ILqo~f;gAUC9-=Ab;^^MO-=#HONL@3WQ*lPOI7 zxw00*6hmc%Ga}5o^v`c|`TWsb$B^RcaHm{Y3^r-DAQERkH%xY=aC0wtA2$*@-hzWR z6oOr}B#-a>75{SuSu~Uta`+}e`o$pHBRTGl0z%9ts2tMaq0HM?JmkG9H+jJMl4Nnw zKX4*D9zaf3G&aDv9nXEnfIrcJoGCR$F{qbKEnR=T1#rnBP!A2_mAMM{h8Arxl#vLD zSHR<_mESlAQE7fmr@aNVx(@p2qlG=Xi)-+!Z8BZ)Qce0*X4Sshs2ICEjyTzEpE0x` zup7ecFXS3%+HD)jeh$VuSEgtoz za`xRwNS#xB#>LysHTraC+&rU>AkXEF5SWt(Bfc^Gk=D*Vt+?)LL%d7*8H`eag2fOk zi&W7+glc6zXnD@ymmco2P_J2JotGp{wvzV<6|%HNSWBE*_Ov0iSY7&jyH_c4`e?ZY;!)l1)zodI&^)frD2G!ZWHyqE@tAx<7A`wbiN_E{ayv1vxP~V zQF&Qaecb`g=`E%&5NBiJois)hudN)}<-`I$@Q=yKts`|E&3PQImlad{l~O!(-ee79 zXl?-!Z(Op@NYk-sNz=3YIMTa@lDGxr{D7}v@Ngk$Q_|o(lL>2jK{zXswT;o=*@Yh; zu$G`hpPmXIy%C--#y^ARwo*bmgrtPg!u7h9;c)=6^{p=0P~Ey zBuXHu8UKhr+iK`R*Ur+O4cFv3tKNj(Tkr29nC)<7{gu$D0aF4(0x&flhSo4hAP5fdXbAat(^sOH~2lm5lfUzMoMF~AaFKn*kaTNL71^JcOhHq zyVk--9zB2R*Lc|3`3wF*`Ke_j<0531TwHd2E*ztQ8&Am?NA%apKG9g=W?=^rPq&;W zDdCU3WWT-v<94VZl}Z6nL7ELA4%j!LJDP9e~ZKF zIQ0uWh!+tRe*9$1o-k=TZM{aHhA+zJ(Q$3`4~?vXZl2~0%n>Dvkc(c3-&=t=&&0q- zP~Ispa8sXQZ`{({dG4VOjE-MrpG&NrWu092Ek;s{6_M1J;3e25he)hD!11#De@Y%?k!fAk&u53W=Z&i1{#z{GEwdGu9et z(FTWvfxs_y#d|M|rwgqI34*>{kjUb%)doIr4DEzp?)|0BF|Av<1;EFo13qt^vzB0V zXKRTUWrgcLVccY&1Jy94M(eesr9nvT(Y3=Woq%As00#oCNnOqqS5VF~yQ;6F6nZn& z^r2^CL{H;4SYHW7rY03S-)EV;Ve=vb-2(7VDPH9?QiQM3zdg(P5=iaryAQwCKNN&0 zT7oZV)OYypcsg$2WU#x&C2S!oNwzZSNP^Or`$p|kjh>0E6AR~l9)p8pjbdSbhYxoJ zU267k0{6Up(;UA@DdAgX_082~(j$4Z3zp57tdg*)#Q~)?r2AS4c`>O?~G^ z;BDeAOEKyxRyHqhKEFJJcqvYG*^(*RGMwB3YI$qEcwVQ2Y0#~UN7x5omWEcO+8$F~ zZqbMx{Ome-9@g@_Ufqo77e8zRM8dhtsgngSR^|(tZd^?wT&Rt<7VP$X+<~1N8v8gN z@W&7_ca^4Iws+l!iY+r7{83*olI@@#M|djsTjT!w zhtk?_TF7kN(r15V3z+ywwn&XR-4x~*203MMY3s=ZCTou~x`mXe1v& zrC1>*@y64lJVBA$Cx%L+-HGpG&XsF7)8=}IJn+HVmWT55Hj4r+wdZ9APc6c#V}G~L zv)nU$VmJ7+tigdGu%g=SUQ6!C`$8cb@u>+Ntwjmp{imNw71d}ol(y8NsbH_!Pu-?K z``C?ok#}+L2KI;!ZPxBjTbQp__B|D2cKxb+1?4uMBa77ROIq43*zG#>2d@&IKYO`$CBaa16Znht+ZC zq1RH6GCK?*0#$sx6rO%IGr>bXH$@xB-5I^bA*8NvvRiAx`lIO>*-F*`dq!sG0 z?vc3)mePv?Zq?r?JiTr-`G-#r$dsxl6!|&gN%z zT$J+5RI8Iiwo{HY*9DEVrr?zfVZy>4`<(GRz(^==UzOCfRJq~>_t^piwfWjwvF~XD zh3+kYA5-$JPJhSk?n2vwEwWI~!(?2PlK%#Eq4hPuv>hgjG_9 zS=DQuuJLi11P-JxXR*Yssn46DHV|sNU5cJU&SMXO;`q%KT4e8tIoMM+$c|F(QTEQJ z3UM5)eM2 zfPfeKUoP1EirIpl3;ZKC+`7XD7j=q+5$=3%H9g)^1UPtc#RN6s*`#iaMN}=I6J4+C z$D4Iat@~dGoU^)5j`niJ-BGQMWHkkdY(xP_?0Zb7n(<1}lh{>Z+nx{>9ZRog(!TY` zbRCb2SM_&kl)Dl^yJ^TGPm&ClzoUwiGj&U622mGfb#qCVWlL{-vJDNl{pvkVgF=Gi z{In3q5nz7%q~}c#%4f~BwO^ftA6zMpX0H*v{QQL6Kd}JW*7NAxTH@e&qtli1b7uX@ z&t3RDE@flcylfWS}H;$HC+qocx8usqId{a(@h|N6M46PUDSI zGhLRzVMEm|#b?}rmth=RL307T3F|+0U$_Nz*L!NnX?Z(w4qVj^U|(1tU?^PWh}|~! zi-Ibf>g(QKZ4M<}&OuN$7B!qQkfYjLK)%^J3gkYwhBXxi+y9Odjb7zB>B~rRF&d2f z6k4%8jeRCKf_;Sk<*)W61ya}JC?N8J#NAmbf@7`@V>%1wqL0b`i2;`ArCvFN^`F+( zs)W}@EAlkRje7Zc1#HSzNc7R!P$5_2+$t1_b5=g@5H?MVS~~anMmY_zCwsn@i^uMzI0^YS5DDQ7Ta5TcufVBQ)op z+IAAlg{=jwsQJmY8(+E1etnzm5QNOMs@Qa`6E|d(dURWlDq*?lt!4HQxT57%(OS(2ueJ?$;OK6 zdXlFX_@DN92v27kOPg4f_n$JxFKbOSCI;fIwpg6IzDiZnmi$>4G6{l8-XwZnO1>F@gbAXI%JxdBX*4tvc!JFlgcMHh< ztIYB{IlpG2=G^Jva30wZs-wdzd&=YZHI9_&@;r5CA@1Sl%38xh;+}f$oebk|`3$-Z zqk1MfX;$Nl+9y#uzhmHf6pO+ZAr=>|#%+WbKSSS3C=D-?oj(i+&lZ2zP57km&n zci<=c*6LcFzu{^|RAFC_=J5E5S))j$mpG6K=DP97ZOWNw|40tA&wj{Q*wy%^GiJIb zZJOHE-X2RW2W+e{@t7~b{>>>EXUz-wjxOA6ws5Je59Q+gqkPJAdg!`QQ46IP75hm3 zF1P%ZrKTruhGoufR^)jUE^)U2lc`V8wx1zXrp&yD z_v0Gpi)+2UA;*fAt3ir$B5R!>uG5mVxFjZxiZYm9RS6=bAa9yCZB*mAg={M9(ge1m zX+*tJpUfr3mC(d>3n(}5&D%PDKl&A-Z#hxkvu3+k2p{MtgqC6oolGn{j3f?NZasPc`^uOs?>JWSICg4tr@&^--&sZU+%ts(# z_4((t6VV@Ze2X2`3DvUP@dh^fs5cKOQ4J>3raE$JM}JS810(|GK(6drw)@lbNcw1p zuR zoCTukQgBCz5>H@B1^LW9D_Ef4rPZeQjSH*xj%zozld?<^D9aX%}Ln)8m+a}$aZ&`-f?4TG6Sj{ZX)4VSk=Dl zyXSKYpgy*rmSiWi>MtwUeM&S*sb?ct`lV7iDzb0#C!)I36;h&8WF>FoY@w(d>_^1& ztUr(7%jqnLgpU)IgsJa<+E%( zo2g9gy#XxgIY#7-D;qGy&E(=mTjso#RsRM39d{b;L@)pL-H(f{kegqviuz^H`LhMo zg2(C8Ue<6E!WWw>B~!Kg4KmD!oLzsx-#5WXw_F z60}e9$Sf@Hlyk_*CJd@2bM!L6CU3Zt&PxK{{;~#W zv0O-9X|VIgnm@9)NOdabXti~&IN5_T^x418W`~ys;G*rv6A=~n)7Y`(<1y};2CA1V zG+7oJ;M3Xk=4;bA)u`~^`$++rJE_Bcfu90UxdEthk%ylAgc)f@{9^=IDZ(F`Kc3Jj z4to3Dr*QxgE|wB2*W~C20@`kBfftKWxjQ%f`2%cSP0DRq#)&?>&$}rabMfzdX?7@H z>e^b+Bn#Nwda(+jmQarog6^!=WZD`Q_iFyC2 zLu%2&@`mLi+Ru017(}P^wwC)9J;@f0nZu<}#M|2>*#8j1dMv9a;nJ^EsQcb^eMgY5 z6|wxsp5GIZtl$^$QTUu8OU@cV#lp}K?n=hJN7cdX$L5_;D) zG}{;}+Td$l)>|0G$CpxJ8 zy*>jB#!Tza9Ih7}ab97+(RN4+_Xw*HvOks5Rq;<$cw?oid6E80d3o+GG8Of8wpAEi zVoQdmTip<}?j>wc`*HL^mhatlAxAmuFsrz) zHZY;x4l(iK6y$;mUE8^$SkMqcu6L%~v4LG7el=&2oJ7U06s;~T|b%NWZ2 z=7%l3+t7B;!_B8yOLksH2;c+Quejrr7EF~?|DR~svPh^bg8Q2j!K5}i}PMTqR zy|t&cSKb^1ffTAZmvuN-{Pp~hpcdSqLvp1lp74-Dec5zImp6BPh1n#G6LC~Z{?qps zAU1XGoG88Zng9lP+Qqtc((*WHGoDoPao&Z5M8Ey==cJFvFAi%;W4(~7-?tNKBDfR9 zj?ZY@5ec7mx&}Hf!J@MYfwj)cyT*1(C4yK81S5Z<n1B`X%=8Z}oZ)>b>UDYp$) zd?0h`SAPO*4?Peb-Rw0MQnRHSrMX4sy!#5&bga^xH~l$Q0vSH;X14$;zBKfw-Vowx z41W1g;a=VEC958ckgVMvg{N(9rf7X_Lv7lQYmEm#t;R|W%h~2HXd2LUL}aZ8OJ6@- zb6hpTnrA@lm=y`Q~R3zxVIj)R{g>=5pGAhVO?=vDLeq=*nT(+GoG5hJKE1_BghG9B`I`gZ0k{b)fkBIEaF-+DhX&aQA+i=2Dn3-@A_g&&~FADwHD8ao_ z6~+8l4rM#%9wykER?T}ne;H_v?4^ClI`=33Ue(w?EcIBKC&NOA%G| zCwbgjQDU59a(&wts|<+2`L>1W?C0AREOF+I2!%LJBX!ylgFk_1^};R|%f;UIAVveO z^}F~{{rZ$GZIL9^T1(II6CW=SW4PxGxvx8NI9`RbyCcjUZ zKHayPt-1!HE%rvu@+QhK(K7%7p>p;R^1$l}^#}XL5$%hTpN(hoD!|p(`q(iOcGAMQ zV{O=vvI>Te4|YWvQCvk(YDjXwQc+HuHN06}dtP0j;$SpX&t3GDr9w&++;bvM(2DJw ffvwwzB+u#5lIn2_{+uQd34hLq|I&|Uw+sIZH4;6t diff --git a/Source/Core/EllipseGeometry.js b/Source/Core/EllipseGeometry.js index d75ff820f593..af314120e99c 100644 --- a/Source/Core/EllipseGeometry.js +++ b/Source/Core/EllipseGeometry.js @@ -36,8 +36,8 @@ define([ var unitQuat = new Quaternion(); var rotMtx = new Matrix3(); - function pointOnEllipsoid(theta, bearing, northVec, eastVec, aSqr, ab, bSqr, mag, unitPos, result) { - var azimuth = theta + bearing; + function pointOnEllipsoid(theta, rotation, northVec, eastVec, aSqr, ab, bSqr, mag, unitPos, result) { + var azimuth = theta + rotation; Cartesian3.multiplyByScalar(eastVec, Math.cos(azimuth), rotAxis); Cartesian3.multiplyByScalar(northVec, Math.sin(azimuth), tempVec); @@ -81,7 +81,7 @@ define([ * @param {Number} options.semiMinorAxis The length of the ellipse's semi-minor axis in meters. * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid the ellipse will be on. * @param {Number} [options.height=0.0] The height above the ellipsoid. - * @param {Number} [options.bearing=0.0] The angle from north (clockwise) in radians. The default is zero. + * @param {Number} [options.rotation=0.0] The angle from north (clockwise) in radians. The default is zero. * @param {Number} [options.granularity=0.02] The angular distance between points on the ellipse in radians. * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed. * @@ -100,7 +100,7 @@ define([ * center : ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-75.59777, 40.03883)), * semiMajorAxis : 500000.0, * semiMinorAxis : 300000.0, - * bearing : CesiumMath.toRadians(60.0) + * rotation : CesiumMath.toRadians(60.0) * }); */ var EllipseGeometry = function(options) { @@ -110,7 +110,7 @@ define([ var semiMinorAxis = options.semiMinorAxis; var ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84); - var bearing = defaultValue(options.bearing, 0.0); + var rotation = defaultValue(options.rotation, 0.0); var height = defaultValue(options.height, 0.0); var granularity = defaultValue(options.granularity, 0.02); @@ -190,8 +190,8 @@ define([ // Compute points in the 'northern' half of the ellipse var theta = CesiumMath.PI_OVER_TWO; for (i = 0; i < numPts && theta > 0; ++i) { - pointOnEllipsoid(theta, bearing, northVec, eastVec, aSqr, ab, bSqr, mag, unitPos, position); - pointOnEllipsoid(Math.PI - theta, bearing, northVec, eastVec, aSqr, ab, bSqr, mag, unitPos, reflectedPosition); + pointOnEllipsoid(theta, rotation, northVec, eastVec, aSqr, ab, bSqr, mag, unitPos, position); + pointOnEllipsoid(Math.PI - theta, rotation, northVec, eastVec, aSqr, ab, bSqr, mag, unitPos, reflectedPosition); positions[positionIndex++] = position.x; positions[positionIndex++] = position.y; @@ -220,8 +220,8 @@ define([ for (i = numPts; i > 0; --i) { theta = CesiumMath.PI_OVER_TWO - (i - 1) * deltaTheta; - pointOnEllipsoid(-theta, bearing, northVec, eastVec, aSqr, ab, bSqr, mag, unitPos, position); - pointOnEllipsoid( theta + Math.PI, bearing, northVec, eastVec, aSqr, ab, bSqr, mag, unitPos, reflectedPosition); + pointOnEllipsoid(-theta, rotation, northVec, eastVec, aSqr, ab, bSqr, mag, unitPos, position); + pointOnEllipsoid( theta + Math.PI, rotation, northVec, eastVec, aSqr, ab, bSqr, mag, unitPos, reflectedPosition); positions[positionIndex++] = position.x; positions[positionIndex++] = position.y; diff --git a/Source/Core/EllipsoidGeometry.js b/Source/Core/EllipsoidGeometry.js index 10718751d342..77900d691fea 100644 --- a/Source/Core/EllipsoidGeometry.js +++ b/Source/Core/EllipsoidGeometry.js @@ -30,9 +30,8 @@ define([ var scratchDirection = new Cartesian3(); function addEdgePositions(i0, i1, numberOfPartitions, positions) { - var indices = []; + var indices = new Array(2 + numberOfPartitions - 1); indices[0] = i0; - indices[2 + (numberOfPartitions - 1) - 1] = i1; var origin = positions[i0]; var direction = Cartesian3.subtract(positions[i1], positions[i0], scratchDirection); @@ -46,6 +45,8 @@ define([ positions.push(position); } + indices[2 + (numberOfPartitions - 1) - 1] = i1; + return indices; } @@ -113,6 +114,7 @@ define([ var normal = new Cartesian3(); var tangent = new Cartesian3(); var binormal = new Cartesian3(); + var defaultRadii = new Cartesian3(1.0, 1.0, 1.0); /** * A {@link Geometry} that represents vertices and indices for an ellipsoid centered at the origin. @@ -120,7 +122,7 @@ define([ * @alias EllipsoidGeometry * @constructor * - * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.UNIT_SPHERE] The ellipsoid used to create vertex attributes. + * @param {Cartesian3} [options.radii=Cartesian3(1.0, 1.0, 1.0)] The radii of the ellipsoid in the x, y, and z directions. * @param {Number} [options.numberOfPartitions=32] The number of times to partition the ellipsoid in a plane formed by two radii in a single quadrant. * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed. * @@ -129,13 +131,14 @@ define([ * @example * var ellipsoid = new EllipsoidGeometry({ * vertexFormat : VertexFormat.POSITION_ONLY, - * ellipsoid : new Ellipsoid(1000000.0, 500000.0, 500000.0) + * radii : new Cartesian3(1000000.0, 500000.0, 500000.0) * }); */ var EllipsoidGeometry = function(options) { options = defaultValue(options, defaultValue.EMPTY_OBJECT); - var ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.UNIT_SPHERE); + var radii = defaultValue(options.radii, defaultRadii); + var ellipsoid = Ellipsoid.fromCartesian3(radii); var numberOfPartitions = defaultValue(options.numberOfPartitions, 32); var vertexFormat = defaultValue(options.vertexFormat, VertexFormat.DEFAULT); diff --git a/Source/Core/Extent.js b/Source/Core/Extent.js index 7e0fbeb29e28..a7c2288c34bf 100644 --- a/Source/Core/Extent.js +++ b/Source/Core/Extent.js @@ -28,7 +28,7 @@ define([ */ var Extent = function(west, south, east, north) { /** - * The westernmost longitude, in radians, in the range [-Pi, Pi]. + * The westernmost longitude in radians in the range [-Pi, Pi]. * * @type {Number} * @default 0.0 @@ -36,7 +36,7 @@ define([ this.west = defaultValue(west, 0.0); /** - * The southernmost latitude, in radians, in the range [-Pi/2, Pi/2]. + * The southernmost latitude in radians in the range [-Pi/2, Pi/2]. * * @type {Number} * @default 0.0 @@ -44,7 +44,7 @@ define([ this.south = defaultValue(south, 0.0); /** - * The easternmost longitude, in radians, in the range [-Pi, Pi]. + * The easternmost longitude in radians in the range [-Pi, Pi]. * * @type {Number} * @default 0.0 @@ -52,7 +52,7 @@ define([ this.east = defaultValue(east, 0.0); /** - * The northernmost latitude, in radians, in the range [-Pi/2, Pi/2]. + * The northernmost latitude in radians in the range [-Pi/2, Pi/2]. * * @type {Number} * @default 0.0 @@ -65,10 +65,10 @@ define([ * * @memberof Extent * - * @param {Number} [west=0.0] The westernmost longitude, in degrees, in the range [-180.0, 180.0]. - * @param {Number} [south=0.0] The southernmost latitude in degrees, in the range [-90.0, 90.0]. - * @param {Number} [east=0.0] The easternmost longitude in degrees, in the range [-180.0, 180.0]. - * @param {Number} [north=0.0] The northernmost latitude in degrees, in the range [-90.0, 90.0]. + * @param {Number} [west=0.0] The westernmost longitude in degrees in the range [-180.0, 180.0]. + * @param {Number} [south=0.0] The southernmost latitude in degrees in the range [-90.0, 90.0]. + * @param {Number} [east=0.0] The easternmost longitude in degrees in the range [-180.0, 180.0]. + * @param {Number} [north=0.0] The northernmost latitude in degrees in the range [-90.0, 90.0]. * @param {Extent} [result] The object onto which to store the result, or undefined if a new instance should be created. * * @return {Extent} The modified result parameter or a new Extent instance if none was provided. diff --git a/Source/Core/ExtentGeometry.js b/Source/Core/ExtentGeometry.js index 082611fed15d..77718ed61960 100644 --- a/Source/Core/ExtentGeometry.js +++ b/Source/Core/ExtentGeometry.js @@ -67,7 +67,7 @@ define([ * @param {Extent} options.extent A cartographic extent with north, south, east and west properties in radians. * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed. * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid on which the extent lies. - * @param {Number} [options.granularity=CesiumMath.toRadians(1.0)] The distance, in radians, between each latitude and longitude. Determines the number of positions in the buffer. + * @param {Number} [options.granularity=CesiumMath.RADIANS_PER_DEGREE] The distance, in radians, between each latitude and longitude. Determines the number of positions in the buffer. * @param {Number} [options.height=0.0] The height from the surface of the ellipsoid. * @param {Number} [options.rotation=0.0] The rotation of the extent in radians. A positive rotation is counter-clockwise. * @@ -97,7 +97,7 @@ define([ extent.validate(); - var granularity = defaultValue(options.granularity, CesiumMath.toRadians(1.0)); + var granularity = defaultValue(options.granularity, CesiumMath.RADIANS_PER_DEGREE); var width = Math.ceil((extent.east - extent.west) / granularity) + 1; var height = Math.ceil((extent.north - extent.south) / granularity) + 1; var granularityX = (extent.east - extent.west) / (width - 1); diff --git a/Source/Core/Geometry.js b/Source/Core/Geometry.js index bb2e7d298f5f..424e08319f5c 100644 --- a/Source/Core/Geometry.js +++ b/Source/Core/Geometry.js @@ -25,7 +25,10 @@ define([ * @alias Geometry * @constructor * - * @param {Object} [options=undefined] An object with properties corresponding to Geometry properties as shown in the code example. + * @param {GeometryAttributes} options.attributes Attributes, which make up the geometry's vertices. + * @param {PrimitiveType} options.primitiveType The type of primitives in the geometry. + * @param {Array} [options.indices] Optional index data that determines the primitives in the geometry. + * @param {BoundingSphere} [options.boundingSphere] An optional bounding sphere that fully enclosed the geometry. * * @example * // Create geometry with a position attribute and indexed lines. @@ -48,6 +51,8 @@ define([ * boundingSphere : BoundingSphere.fromVertices(positions) * }); * + * @demo Geometry and Appearances Demo + * * @see PolygonGeometry * @see ExtentGeometry * @see EllipseGeometry @@ -60,6 +65,14 @@ define([ var Geometry = function(options) { options = defaultValue(options, defaultValue.EMPTY_OBJECT); + if (typeof options.attributes === 'undefined') { + throw new DeveloperError('options.attributes is required.'); + } + + if (typeof options.primitiveType === 'undefined') { + throw new DeveloperError('options.primitiveType is required.'); + } + /** * Attributes, which make up the geometry's vertices. Each property in this object corresponds to a * {@link GeometryAttribute} containing the attribute's data. @@ -107,7 +120,7 @@ define([ * @see GeometryAttribute * @see VertexFormat */ - this.attributes = defaultValue(options.attributes, {}); + this.attributes = options.attributes; /** * Optional index data that - along with {@link Geometry#primitiveType} - @@ -116,11 +129,6 @@ define([ * @type Array * * @default undefined - * - * @example - * // Two triangles with shared vertices - * geometry.primitiveType = PrimitiveType.TRIANGLES; - * geometry.indices = new Uint16Array([0, 1, 2, 0, 2, 3]); */ this.indices = options.indices; @@ -131,71 +139,20 @@ define([ * @type PrimitiveType * * @default undefined - * - * @example - * // Two triangles with shared vertices - * geometry.primitiveType = PrimitiveType.TRIANGLES; - * geometry.indices = new Uint16Array([0, 1, 2, 0, 2, 3]); */ this.primitiveType = options.primitiveType; /** - * An optional bounding sphere that fully enclosed the geometry. This is + * An optional bounding sphere that fully encloses the geometry. This is * commonly used for culling. * * @type BoundingSphere * * @default undefined - * - * @example - * geometry.boundingSphere = BoundingSphere.fromVertices(positions); */ this.boundingSphere = options.boundingSphere; }; - /** - * Duplicates a Geometry instance, including a deep copy of the attributes and indices. - * - * @memberof Geometry - * - * @param {Geometry} geometry The geometry to duplicate. If this is undefined, undefined is returned. - * @param {Geometry} [result] The object onto which to store the result. - * - * @return {Geometry} The modified result parameter or a new Geometry instance if one was not provided. - * - * @example - * result.geometry = Geometry.clone(this.geometry); - */ - Geometry.clone = function(geometry, result) { - if (typeof geometry === 'undefined') { - return undefined; - } - - if (typeof result === 'undefined') { - result = new Geometry(); - } - - var attributes = geometry.attributes; - var newAttributes = {}; - for (var property in attributes) { - if (attributes.hasOwnProperty(property) && typeof attributes[property] !== 'undefined') { - newAttributes[property] = attributes[property].clone(); - } - } - result.attributes = newAttributes; - - if (typeof geometry.indices !== 'undefined') { - var sourceValues = geometry.indices; - result.indices = new sourceValues.constructor(sourceValues); - } else { - result.indices = undefined; - } - result.primitiveType = geometry.primitiveType; - result.boundingSphere = BoundingSphere.clone(geometry.boundingSphere, result.boundingSphere); - - return result; - }; - /** * Computes the number of vertices in a geometry. The runtime is linear with * respect to the number of attributes in a vertex, not the number of vertices. diff --git a/Source/Core/GeometryAttribute.js b/Source/Core/GeometryAttribute.js index 10908318dcf5..f79cbab7a795 100644 --- a/Source/Core/GeometryAttribute.js +++ b/Source/Core/GeometryAttribute.js @@ -1,8 +1,10 @@ /*global define*/ define([ - './defaultValue' + './defaultValue', + './DeveloperError' ], function( - defaultValue) { + defaultValue, + DeveloperError) { "use strict"; /** @@ -18,6 +20,11 @@ define([ * @param {Boolean} [options.normalize=false] When true and componentDatatype is an integer format, indicate that the components should be mapped to the range [0, 1] (unsigned) or [-1, 1] (signed) when they are accessed as floating-point for rendering. * @param {Array} [options.values=undefined] The values for the attributes stored in a typed array. * + * @exception {DeveloperError} options.componentDatatype is required. + * @exception {DeveloperError} options.componentsPerAttribute is required. + * @exception {DeveloperError} options.componentsPerAttribute must be between 1 and 4. + * @exception {DeveloperError} options.values is required. + * * @example * var geometry = new Geometry({ * attributes : { @@ -39,6 +46,22 @@ define([ var GeometryAttribute = function(options) { options = defaultValue(options, defaultValue.EMPTY_OBJECT); + if (typeof options.componentDatatype === 'undefined') { + throw new DeveloperError('options.componentDatatype is required.'); + } + + if (typeof options.componentsPerAttribute === 'undefined') { + throw new DeveloperError('options.componentsPerAttribute is required.'); + } + + if (options.componentsPerAttribute < 1 || options.componentsPerAttribute > 4) { + throw new DeveloperError('options.componentsPerAttribute must be between 1 and 4.'); + } + + if (typeof options.values === 'undefined') { + throw new DeveloperError('options.values is required.'); + } + /** * The datatype of each component in the attribute, e.g., individual elements in * {@see GeometryAttribute#values}. @@ -115,27 +138,5 @@ define([ this.values = options.values; }; - /** - * Duplicates a GeometryAttribute instance, including a deep copy of {@link GeometryAttribute#values}. - * - * @memberof Geometry - * - * @param {GeometryAttribute} [result] The object onto which to store the result. - * - * @return {GeometryAttribute} The modified result parameter or a new GeometryAttribute instance if one was not provided. - */ - GeometryAttribute.prototype.clone = function(result) { - if (typeof result === 'undefined') { - result = new GeometryAttribute(); - } - - result.componentDatatype = this.componentDatatype; - result.componentsPerAttribute = this.componentsPerAttribute; - result.normalize = this.normalize; - result.values = new this.values.constructor(this.values); - - return result; - }; - return GeometryAttribute; }); diff --git a/Source/Core/GeometryInstance.js b/Source/Core/GeometryInstance.js index a8c7f1b46141..fc19edca2b63 100644 --- a/Source/Core/GeometryInstance.js +++ b/Source/Core/GeometryInstance.js @@ -1,11 +1,13 @@ /*global define*/ define([ './defaultValue', + './DeveloperError', './Matrix4', './Geometry', './GeometryInstanceAttribute' ], function( defaultValue, + DeveloperError, Matrix4, Geometry, GeometryInstanceAttribute) { @@ -20,11 +22,13 @@ define([ * @alias GeometryInstance * @constructor * - * @param {Geometry} [options.geometry=undefined] The geometry to instance. + * @param {Geometry} options.geometry The geometry to instance. * @param {Matrix4} [options.modelMatrix=Matrix4.IDENTITY] The model matrix that transforms to transform the geometry from model to world coordinates. * @param {Object} [options.id=undefined] A user-defined object to return when the instance is picked with {@link Context#pick} or get/set per-instance attributes with {@link Primitive#getGeometryInstanceAttributes}. * @param {Object} [options.attributes] Per-instance attributes like a show or color attribute shown in the example below. * + * @exception {DeveloperError} options.geometry is required. + * * @example * // Create geometry for a box, and two instances that refer to it. * // One instance positions the box on the bottom and colored aqua. @@ -57,6 +61,10 @@ define([ var GeometryInstance = function(options) { options = defaultValue(options, defaultValue.EMPTY_OBJECT); + if (typeof options.geometry === 'undefined') { + throw new DeveloperError('options.geometry is required.'); + } + /** * The geometry being instanced. * @@ -76,7 +84,7 @@ define([ * * @default Matrix4.IDENTITY */ - this.modelMatrix = defaultValue(options.modelMatrix, Matrix4.IDENTITY.clone()); + this.modelMatrix = Matrix4.clone(defaultValue(options.modelMatrix, Matrix4.IDENTITY)); /** * User-defined object returned when the instance is picked or used to get/set per-instance attributes. @@ -101,40 +109,5 @@ define([ this.attributes = defaultValue(options.attributes, {}); }; - /** - * Duplicates a GeometryInstance instance, including a deep copy of the geometry. - *

    - * {@link GeometryInstance#id} is shallow copied so that the same - * id reference is returned by {@link Context#pick} regardless of - * if the geometry instance was cloned. - *

    - * - * @memberof GeometryInstance - * - * @param {Geometry} [result] The object onto which to store the result. - * - * @return {Geometry} The modified result parameter or a new GeometryInstance instance if one was not provided. - */ - GeometryInstance.prototype.clone = function(result) { - if (typeof result === 'undefined') { - result = new GeometryInstance(); - } - - result.geometry = Geometry.clone(this.geometry); // Looses type info, e.g., BoxGeometry to Geometry. - result.modelMatrix = this.modelMatrix.clone(result.modelMatrix); - result.id = this.id; // Shallow copy - - var attributes = this.attributes; - var newAttributes = {}; - for (var property in attributes) { - if (attributes.hasOwnProperty(property)) { - newAttributes[property] = GeometryInstanceAttribute.clone(attributes[property]); - } - } - result.attributes = newAttributes; - - return result; - }; - return GeometryInstance; }); diff --git a/Source/Core/GeometryInstanceAttribute.js b/Source/Core/GeometryInstanceAttribute.js index b2531597ab4f..ef9ef7d833ca 100644 --- a/Source/Core/GeometryInstanceAttribute.js +++ b/Source/Core/GeometryInstanceAttribute.js @@ -16,6 +16,11 @@ define([ * @param {Boolean} [options.normalize=false] When true and componentDatatype is an integer format, indicate that the components should be mapped to the range [0, 1] (unsigned) or [-1, 1] (signed) when they are accessed as floating-point for rendering. * @param {Array} [options.value=undefined] The value for the attribute. * + * @exception {DeveloperError} options.componentDatatype is required. + * @exception {DeveloperError} options.componentsPerAttribute is required. + * @exception {DeveloperError} options.componentsPerAttribute must be between 1 and 4. + * @exception {DeveloperError} options.value is required. + * * @example * var instance = new GeometryInstance({ * geometry : new BoxGeometry({ @@ -40,6 +45,22 @@ define([ var GeometryInstanceAttribute = function(options) { options = defaultValue(options, defaultValue.EMPTY_OBJECT); + if (typeof options.componentDatatype === 'undefined') { + throw new DeveloperError('options.componentDatatype is required.'); + } + + if (typeof options.componentsPerAttribute === 'undefined') { + throw new DeveloperError('options.componentsPerAttribute is required.'); + } + + if (options.componentsPerAttribute < 1 || options.componentsPerAttribute > 4) { + throw new DeveloperError('options.componentsPerAttribute must be between 1 and 4.'); + } + + if (typeof options.value === 'undefined') { + throw new DeveloperError('options.value is required.'); + } + /** * The datatype of each component in the attribute, e.g., individual elements in * {@see GeometryInstanceAttribute#value}. @@ -112,26 +133,5 @@ define([ this.value = options.value; }; - /** - * Duplicates a GeometryInstanceAttribute instance. - * - * @param {GeometryInstanceAttribute} instanceAttribute The per-instance attribute to clone. - * @param {GeometryInstanceAttribute} [result] The object onto which to store the result. - * - * @return {GeometryInstanceAttribute} The modified result parameter or a new GeometryInstanceAttribute instance if one was not provided. - */ - GeometryInstanceAttribute.clone = function(instanceAttribute, result) { - if (typeof result === 'undefined') { - result = new GeometryInstanceAttribute(); - } - - result.componentDatatype = instanceAttribute.componentDatatype; - result.componentsPerAttribute = instanceAttribute.componentsPerAttribute; - result.normalize = instanceAttribute.normalize; - result.value = new instanceAttribute.value.constructor(instanceAttribute.value); - - return result; - }; - return GeometryInstanceAttribute; }); diff --git a/Source/Core/GeometryPipeline.js b/Source/Core/GeometryPipeline.js index 728e5366f02a..8f589b1375ea 100644 --- a/Source/Core/GeometryPipeline.js +++ b/Source/Core/GeometryPipeline.js @@ -362,7 +362,10 @@ define([ // Reorder attributes var attributes = geometry.attributes; for ( var property in attributes) { - if (attributes.hasOwnProperty(property) && attributes[property].values) { + if (attributes.hasOwnProperty(property) && + typeof attributes[property] !== 'undefined' && + typeof attributes[property].values !== 'undefined') { + var attribute = attributes[property]; var elementsIn = attribute.values; var intoElementsIn = 0; @@ -797,7 +800,10 @@ define([ var name; for (name in attributes0) { - if (attributes0.hasOwnProperty(name)) { + if (attributes0.hasOwnProperty(name) && + typeof attributes0[name] !== 'undefined' && + typeof attributes0[name].values !== 'undefined') { + var attribute = attributes0[name]; var numberOfComponents = attribute.values.length; var inAllGeometries = true; @@ -928,7 +934,8 @@ define([ } var numberOfVertices = Geometry.computeNumberOfVertices(new Geometry({ - attributes : attributes + attributes : attributes, + primitiveType : PrimitiveType.POINTS })); var destIndices = IndexDatatype.createTypedArray(numberOfVertices, numberOfIndices); diff --git a/Source/Core/PolygonGeometry.js b/Source/Core/PolygonGeometry.js index a9e5f07fc807..70439d6d4294 100644 --- a/Source/Core/PolygonGeometry.js +++ b/Source/Core/PolygonGeometry.js @@ -133,7 +133,7 @@ define([ * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed. * @param {Number} [options.stRotation=0.0] The rotation of the texture coordiantes, in radians. A positive rotation is counter-clockwise. * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid to be used as a reference. - * @param {Number} [options.granularity=CesiumMath.toRadians(1.0)] The distance, in radians, between each latitude and longitude. Determines the number of positions in the buffer. + * @param {Number} [options.granularity=CesiumMath.RADIANS_PER_DEGREE] The distance, in radians, between each latitude and longitude. Determines the number of positions in the buffer. * * @exception {DeveloperError} At least three positions are required. * @exception {DeveloperError} positions or polygonHierarchy must be supplied. @@ -192,7 +192,7 @@ define([ var vertexFormat = defaultValue(options.vertexFormat, VertexFormat.DEFAULT); var ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84); - var granularity = defaultValue(options.granularity, CesiumMath.toRadians(1.0)); + var granularity = defaultValue(options.granularity, CesiumMath.RADIANS_PER_DEGREE); var stRotation = defaultValue(options.stRotation, 0.0); var height = defaultValue(options.height, 0.0); diff --git a/Source/Core/PolygonPipeline.js b/Source/Core/PolygonPipeline.js index 67dde97c39fe..441177800c51 100644 --- a/Source/Core/PolygonPipeline.js +++ b/Source/Core/PolygonPipeline.js @@ -572,7 +572,7 @@ define([ throw new DeveloperError('The number of indices must be divisable by three.'); } - granularity = defaultValue(granularity, CesiumMath.toRadians(1.0)); + granularity = defaultValue(granularity, CesiumMath.RADIANS_PER_DEGREE); if (granularity <= 0.0) { throw new DeveloperError('granularity must be greater than zero.'); } diff --git a/Source/Core/Shapes.js b/Source/Core/Shapes.js index 296b1c052f7e..fa62956ca3bb 100644 --- a/Source/Core/Shapes.js +++ b/Source/Core/Shapes.js @@ -110,7 +110,7 @@ define([ throw new DeveloperError('radius must be greater than zero.'); } - granularity = defaultValue(granularity, CesiumMath.toRadians(1.0)); + granularity = defaultValue(granularity, CesiumMath.RADIANS_PER_DEGREE); if (granularity <= 0.0) { throw new DeveloperError('granularity must be greater than zero.'); } @@ -162,7 +162,7 @@ define([ } bearing = bearing || 0.0; - granularity = defaultValue(granularity, CesiumMath.toRadians(1.0)); + granularity = defaultValue(granularity, CesiumMath.RADIANS_PER_DEGREE); if (granularity <= 0.0) { throw new DeveloperError('granularity must be greater than zero.'); diff --git a/Source/Renderer/Context.js b/Source/Renderer/Context.js index 186699be8a1d..afe700d5ebbc 100644 --- a/Source/Renderer/Context.js +++ b/Source/Renderer/Context.js @@ -2201,7 +2201,9 @@ define([ var names = []; for (name in attributes) { // Attribute needs to have per-vertex values; not a constant value for all vertices. - if (attributes.hasOwnProperty(name) && typeof attributes[name].values !== 'undefined') { + if (attributes.hasOwnProperty(name) && + typeof attributes[name] !== 'undefined' && + typeof attributes[name].values !== 'undefined') { names.push(name); if (attributes[name].componentDatatype === ComponentDatatype.DOUBLE) { @@ -2389,7 +2391,7 @@ define([ var strideInBytes = interleavedAttributes.vertexSizeInBytes; for (name in attributes) { - if (attributes.hasOwnProperty(name)) { + if (attributes.hasOwnProperty(name) && typeof attributes[name] !== 'undefined') { attribute = attributes[name]; if (typeof attribute.values !== 'undefined') { diff --git a/Source/Scene/CentralBodySurface.js b/Source/Scene/CentralBodySurface.js index 04e893ff671a..dc47cb7de0f3 100644 --- a/Source/Scene/CentralBodySurface.js +++ b/Source/Scene/CentralBodySurface.js @@ -709,7 +709,7 @@ define([ if (!surface._debug.boundingSphereVA) { var radius = surface._debug.boundingSphereTile.boundingSphere3D.radius; var sphere = new EllipsoidGeometry({ - ellipsoid : new Ellipsoid(radius, radius, radius), + radii : new Cartesian3(radius, radius, radius), numberOfPartitions : 10 }); GeometryPipeline.toWireframe(sphere); diff --git a/Source/Scene/ExtentPrimitive.js b/Source/Scene/ExtentPrimitive.js index d18050e6ccfd..6a49e3abbb88 100644 --- a/Source/Scene/ExtentPrimitive.js +++ b/Source/Scene/ExtentPrimitive.js @@ -35,7 +35,7 @@ define([ * * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid that the extent is drawn on. * @param {Extent} [extent=undefined] The extent, which defines the rectangular region to draw. - * @param {Number} [granularity=CesiumMath.toRadians(1.0)] The distance, in radians, between each latitude and longitude in the underlying geometry. + * @param {Number} [granularity=CesiumMath.RADIANS_PER_DEGREE] The distance, in radians, between each latitude and longitude in the underlying geometry. * @param {Number} [height=0.0] The height, in meters, that the extent is raised above the {@link ExtentPrimitive#ellipsoid}. * @param {Number} [rotation=0.0] The angle, in radians, relative to north that the extent is rotated. Positive angles rotate counter-clockwise. * @param {Boolean} [show=true] Determines if this primitive will be shown. @@ -77,9 +77,9 @@ define([ * * @type Number * - * @default CesiumMath.toRadians(1.0) + * @default CesiumMath.RADIANS_PER_DEGREE */ - this.granularity = defaultValue(options.granularity, CesiumMath.toRadians(1.0)); + this.granularity = defaultValue(options.granularity, CesiumMath.RADIANS_PER_DEGREE); this._granularity = undefined; /** diff --git a/Source/Scene/Polygon.js b/Source/Scene/Polygon.js index 02d6d5836e79..b6949651cc22 100644 --- a/Source/Scene/Polygon.js +++ b/Source/Scene/Polygon.js @@ -71,9 +71,9 @@ define([ * * @type Number * - * @default CesiumMath.toRadians(1.0) + * @default CesiumMath.RADIANS_PER_DEGREE */ - this.granularity = defaultValue(options.granularity, CesiumMath.toRadians(1.0)); + this.granularity = defaultValue(options.granularity, CesiumMath.RADIANS_PER_DEGREE); this._granularity = undefined; /** diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index 1b5f9b559b72..e9d2092ec5dd 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -11,6 +11,9 @@ define([ '../Core/BoundingSphere', '../Core/Geometry', '../Core/GeometryAttribute', + '../Core/GeometryAttributes', + '../Core/GeometryInstance', + '../Core/GeometryInstanceAttribute', '../Core/ComponentDatatype', '../Core/Cartesian3', '../Renderer/BufferUsage', @@ -31,6 +34,9 @@ define([ BoundingSphere, Geometry, GeometryAttribute, + GeometryAttributes, + GeometryInstance, + GeometryInstanceAttribute, ComponentDatatype, Cartesian3, BufferUsage, @@ -105,7 +111,7 @@ define([ * var ellipsoidInstance = new GeometryInstance({ * geometry : new EllipsoidGeometry({ * vertexFormat : VertexFormat.POSITION_AND_NORMAL, - * ellipsoid : new Ellipsoid(500000.0, 500000.0, 1000000.0) + * radii : new Cartesian3(500000.0, 500000.0, 1000000.0) * }), * modelMatrix : Matrix4.multiplyByTranslation(Transforms.eastNorthUpToFixedFrame( * ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-95.59777, 40.03883))), new Cartesian3(0.0, 0.0, 500000.0)), @@ -208,6 +214,64 @@ define([ this._commandLists = new CommandLists(); }; + function cloneAttribute(attribute) { + return new GeometryAttribute({ + componentDatatype : attribute.componentDatatype, + componentsPerAttribute : attribute.componentsPerAttribute, + normalize : attribute.normalize, + values : new attribute.values.constructor(attribute.values) + }); + } + + function cloneGeometry(geometry) { + var attributes = geometry.attributes; + var newAttributes = new GeometryAttributes(); + for (var property in attributes) { + if (attributes.hasOwnProperty(property) && typeof attributes[property] !== 'undefined') { + newAttributes[property] = cloneAttribute(attributes[property]); + } + } + + var indices; + if (typeof geometry.indices !== 'undefined') { + var sourceValues = geometry.indices; + indices = new sourceValues.constructor(sourceValues); + } + + return new Geometry({ + attributes : newAttributes, + indices : indices, + primitiveType : geometry.primitiveType, + boundingSphere : BoundingSphere.clone(geometry.boundingSphere) + }); + } + + function cloneGeometryInstanceAttribute(attribute) { + return new GeometryInstanceAttribute({ + componentDatatype : attribute.componentDatatype, + componentsPerAttribute : attribute.componentsPerAttribute, + normalize : attribute.normalize, + value : new attribute.value.constructor(attribute.value) + }); + } + + function cloneInstance(instance) { + var attributes = instance.attributes; + var newAttributes = {}; + for (var property in attributes) { + if (attributes.hasOwnProperty(property)) { + newAttributes[property] = cloneGeometryInstanceAttribute(attributes[property]); + } + } + + return new GeometryInstance({ + geometry : cloneGeometry(instance.geometry), + modelMatrix : Matrix4.clone(instance.modelMatrix), + id : instance.id, // Shallow copy + attributes : newAttributes + }); + } + function addPickColorAttribute(primitive, instances, context) { var length = instances.length; @@ -624,7 +688,7 @@ define([ length = instances.length; var insts = new Array(length); for (i = 0; i < length; ++i) { - insts[i] = instances[i].clone(); + insts[i] = cloneInstance(instances[i]); } var geometries = geometryPipeline(this, insts, context, projection); diff --git a/Source/Scene/SkyAtmosphere.js b/Source/Scene/SkyAtmosphere.js index 325673f7793b..389beb7f1f9f 100644 --- a/Source/Scene/SkyAtmosphere.js +++ b/Source/Scene/SkyAtmosphere.js @@ -132,7 +132,7 @@ define([ if (typeof command.vertexArray === 'undefined') { var geometry = new EllipsoidGeometry({ - ellipsoid : Ellipsoid.fromCartesian3(this._ellipsoid.getRadii().multiplyByScalar(1.025)), + radii : this._ellipsoid.getRadii().multiplyByScalar(1.025), numberOfPartitions : 60 }); command.vertexArray = context.createVertexArrayFromGeometry({ diff --git a/Source/Scene/SunPostProcess.js b/Source/Scene/SunPostProcess.js index 24e939162490..9af0f6ff7bdb 100644 --- a/Source/Scene/SunPostProcess.js +++ b/Source/Scene/SunPostProcess.js @@ -140,7 +140,8 @@ define([ 0.0, 1.0 ] }) - } + }, + primitiveType : PrimitiveType.TRIANGLES }); vertexArray = context.createVertexArrayFromGeometry({ diff --git a/Source/Scene/ViewportQuad.js b/Source/Scene/ViewportQuad.js index d1e0f969eaa1..a72e3d8eeb6b 100644 --- a/Source/Scene/ViewportQuad.js +++ b/Source/Scene/ViewportQuad.js @@ -143,7 +143,8 @@ define([ 0.0, 1.0 ] }) - } + }, + primitiveType : PrimitiveType.TRIANGLES }); vertexArray = context.createVertexArrayFromGeometry({ diff --git a/Specs/Core/EllipsoidGeometrySpec.js b/Specs/Core/EllipsoidGeometrySpec.js index f4332794cb5d..40434b69c0d8 100644 --- a/Specs/Core/EllipsoidGeometrySpec.js +++ b/Specs/Core/EllipsoidGeometrySpec.js @@ -25,7 +25,6 @@ defineSuite([ it('computes positions', function() { var m = new EllipsoidGeometry({ vertexFormat : VertexFormat.POSITION_ONLY, - ellipsoid : Ellipsoid.UNIT_SPHERE, numberOfPartitions : 1 }); @@ -37,7 +36,6 @@ defineSuite([ it('compute all vertex attributes', function() { var m = new EllipsoidGeometry({ vertexFormat : VertexFormat.ALL, - ellipsoid : Ellipsoid.UNIT_SPHERE, numberOfPartitions : 2 }); @@ -52,7 +50,6 @@ defineSuite([ it('computes attributes for a unit sphere', function() { var m = new EllipsoidGeometry({ vertexFormat : VertexFormat.ALL, - ellipsoid : Ellipsoid.UNIT_SPHERE, numberOfPartitions : 3 }); diff --git a/Specs/Core/GeometryAttributeSpec.js b/Specs/Core/GeometryAttributeSpec.js index 2a53dbd70ab7..f1d8d108da8d 100644 --- a/Specs/Core/GeometryAttributeSpec.js +++ b/Specs/Core/GeometryAttributeSpec.js @@ -30,56 +30,53 @@ defineSuite([ ]); }); - it('clone', function() { - var color = new GeometryAttribute({ - componentDatatype : ComponentDatatype.UNSIGNED_BYTE, - componentsPerAttribute : 4, - normalize : true, - values : new Uint8Array([ - 255, 0, 0, 255, - 0, 255, 0, 255, - 0, 0, 255, 255 - ]) - }); - var clone = color.clone(); + it('constructor throws without componentDatatype', function() { + expect(function() { + return new GeometryAttribute({ + componentsPerAttribute : 4, + values : new Uint8Array([ + 255, 0, 0, 255, + 0, 255, 0, 255, + 0, 0, 255, 255 + ]) + }); + }).toThrow(); + }); - expect(clone.componentDatatype).toEqual(ComponentDatatype.UNSIGNED_BYTE); - expect(clone.componentsPerAttribute).toEqual(4); - expect(clone.normalize).toEqual(true); - expect(clone.values).not.toBe(color.values); - expect(clone.values instanceof Uint8Array); - expect(clone.values).toEqual([ - 255, 0, 0, 255, - 0, 255, 0, 255, - 0, 0, 255, 255 - ]); + it('constructor throws without componentsPerAttribute', function() { + expect(function() { + return new GeometryAttribute({ + componentDatatype : ComponentDatatype.UNSIGNED_BYTE, + values : new Uint8Array([ + 255, 0, 0, 255, + 0, 255, 0, 255, + 0, 0, 255, 255 + ]) + }); + }).toThrow(); }); - it('clone with result parameter', function() { - var color = new GeometryAttribute({ - componentDatatype : ComponentDatatype.UNSIGNED_BYTE, - componentsPerAttribute : 4, - normalize : true, - values : new Uint8Array([ - 255, 0, 0, 255, - 0, 255, 0, 255, - 0, 0, 255, 255 - ]) - }); - var result = new GeometryAttribute(); - var clone = color.clone(result); + it('constructor throws when componentsPerAttribute is less than 1 or greater than 4', function() { + expect(function() { + return new GeometryAttribute({ + componentDatatype : ComponentDatatype.UNSIGNED_BYTE, + componentsPerAttribute : 7, + values : new Uint8Array([ + 255, 0, 0, 255, + 0, 255, 0, 255, + 0, 0, 255, 255 + ]) + }); + }).toThrow(); + }); - expect(clone).toBe(result); - expect(clone.componentDatatype).toEqual(ComponentDatatype.UNSIGNED_BYTE); - expect(clone.componentsPerAttribute).toEqual(4); - expect(clone.normalize).toEqual(true); - expect(clone.values).not.toBe(color.values); - expect(clone.values instanceof Uint8Array); - expect(clone.values).toEqual([ - 255, 0, 0, 255, - 0, 255, 0, 255, - 0, 0, 255, 255 - ]); + it('constructor throws without values', function() { + expect(function() { + return new GeometryAttribute({ + componentDatatype : ComponentDatatype.UNSIGNED_BYTE, + componentsPerAttribute : 4 + }); + }).toThrow(); }); }); diff --git a/Specs/Core/GeometryInstanceAttributeSpec.js b/Specs/Core/GeometryInstanceAttributeSpec.js index 77a460a86704..32bdfa941679 100644 --- a/Specs/Core/GeometryInstanceAttributeSpec.js +++ b/Specs/Core/GeometryInstanceAttributeSpec.js @@ -22,40 +22,41 @@ defineSuite([ expect(color.value).toEqual([255, 255, 0, 255]); }); - it('clone', function() { - var color = new GeometryInstanceAttribute({ - componentDatatype : ComponentDatatype.UNSIGNED_BYTE, - componentsPerAttribute : 4, - normalize : true, - value : new Uint8Array([255, 255, 0, 255]) - }); - var clone = GeometryInstanceAttribute.clone(color); + it('constructor throws without componentDatatype', function() { + expect(function() { + return new GeometryAttribute({ + componentsPerAttribute : 4, + value : new Uint8Array([255, 255, 0, 255]) + }); + }).toThrow(); + }); - expect(clone.componentDatatype).toEqual(ComponentDatatype.UNSIGNED_BYTE); - expect(clone.componentsPerAttribute).toEqual(4); - expect(clone.normalize).toEqual(true); - expect(clone.value).not.toBe(color.value); - expect(clone.value instanceof Uint8Array); - expect(color.value).toEqual([255, 255, 0, 255]); + it('constructor throws without componentsPerAttribute', function() { + expect(function() { + return new GeometryAttribute({ + componentDatatype : ComponentDatatype.UNSIGNED_BYTE, + value : new Uint8Array([255, 255, 0, 255]) + }); + }).toThrow(); }); - it('clone with result parameter', function() { - var color = new GeometryInstanceAttribute({ - componentDatatype : ComponentDatatype.UNSIGNED_BYTE, - componentsPerAttribute : 4, - normalize : true, - value : new Uint8Array([255, 255, 0, 255]) - }); - var result = new GeometryInstanceAttribute(); - var clone = GeometryInstanceAttribute.clone(color, result); + it('constructor throws when componentsPerAttribute is less than 1 or greater than 4', function() { + expect(function() { + return new GeometryAttribute({ + componentDatatype : ComponentDatatype.UNSIGNED_BYTE, + componentsPerAttribute : 7, + value : new Uint8Array([255, 255, 0, 255]) + }); + }).toThrow(); + }); - expect(clone).toBe(result); - expect(clone.componentDatatype).toEqual(ComponentDatatype.UNSIGNED_BYTE); - expect(clone.componentsPerAttribute).toEqual(4); - expect(clone.normalize).toEqual(true); - expect(clone.value).not.toBe(color.value); - expect(clone.value instanceof Uint8Array); - expect(color.value).toEqual([255, 255, 0, 255]); + it('constructor throws without values', function() { + expect(function() { + return new GeometryAttribute({ + componentDatatype : ComponentDatatype.UNSIGNED_BYTE, + componentsPerAttribute : 4 + }); + }).toThrow(); }); }); diff --git a/Specs/Core/GeometryInstanceSpec.js b/Specs/Core/GeometryInstanceSpec.js index 00a0453a2b91..152e5f1e89b1 100644 --- a/Specs/Core/GeometryInstanceSpec.js +++ b/Specs/Core/GeometryInstanceSpec.js @@ -61,99 +61,10 @@ defineSuite([ expect(attributes).toBe(attributes); }); - it('clone', function() { - var geometry = new Geometry({ - attributes : { - position : new GeometryAttribute({ - componentDatatype : ComponentDatatype.DOUBLE, - componentsPerAttribute : 3, - values : new Float64Array([ - 0.0, 0.0, 0.0, - 1.0, 0.0, 0.0, - 0.0, 1.0, 0.0 - ]) - }) - }, - indices : new Uint16Array([0, 1, 2]), - primitiveType : PrimitiveType.TRIANGLES, - boundingSphere : new BoundingSphere(new Cartesian3(0.5, 0.5, 0.0), 1.0) - }); - var modelMatrix = Matrix4.multiplyByTranslation(Matrix4.IDENTITY, new Cartesian3(0.0, 0.0, 9000000.0)); - var attributes = { - color : new GeometryInstanceAttribute({ - componentDatatype : ComponentDatatype.UNSIGNED_BYTE, - componentsPerAttribute : 4, - normalize : true, - value : new Uint8Array([255, 255, 0, 255]) - }) - }; - var instance = new GeometryInstance({ - geometry : geometry, - modelMatrix : modelMatrix, - id : 'geometry', - attributes : attributes - }); - var clone = instance.clone(); - - expect(clone.geometry).toBeDefined(); - expect(clone.geometry.attributes).toBeDefined(); - expect(clone.geometry.attributes.position).toBeDefined(); - expect(clone.geometry.indices).toBeDefined(); - - expect(clone.modelMatrix).toEqual(instance.modelMatrix); - expect(clone.id).toEqual(instance.id); - - expect(clone.attributes).toBeDefined(); - expect(clone.attributes.color).toBeDefined(); - }); - - it('clone with result parameter', function() { - var geometry = new Geometry({ - attributes : { - position : new GeometryAttribute({ - componentDatatype : ComponentDatatype.DOUBLE, - componentsPerAttribute : 3, - values : new Float64Array([ - 0.0, 0.0, 0.0, - 1.0, 0.0, 0.0, - 0.0, 1.0, 0.0 - ]) - }) - }, - indices : new Uint16Array([0, 1, 2]), - primitiveType : PrimitiveType.TRIANGLES, - boundingSphere : new BoundingSphere(new Cartesian3(0.5, 0.5, 0.0), 1.0) - }); - var modelMatrix = Matrix4.multiplyByTranslation(Matrix4.IDENTITY, new Cartesian3(0.0, 0.0, 9000000.0)); - var attributes = { - color : new GeometryInstanceAttribute({ - componentDatatype : ComponentDatatype.UNSIGNED_BYTE, - componentsPerAttribute : 4, - normalize : true, - value : new Uint8Array([255, 255, 0, 255]) - }) - }; - var instance = new GeometryInstance({ - geometry : geometry, - modelMatrix : modelMatrix, - id : 'geometry', - attributes : attributes - }); - var result = new GeometryInstance(); - var clone = instance.clone(result); - - expect(clone).toBe(result); - - expect(clone.geometry).toBeDefined(); - expect(clone.geometry.attributes).toBeDefined(); - expect(clone.geometry.attributes.position).toBeDefined(); - expect(clone.geometry.indices).toBeDefined(); - - expect(clone.modelMatrix).toEqual(instance.modelMatrix); - expect(clone.id).toEqual(instance.id); - - expect(clone.attributes).toBeDefined(); - expect(clone.attributes.color).toBeDefined(); + it('constructor throws without geometry', function() { + expect(function() { + return new GeometryInstance(); + }).toThrow(); }); }); diff --git a/Specs/Core/GeometryPipelineSpec.js b/Specs/Core/GeometryPipelineSpec.js index 52b095cb1f59..13893f372562 100644 --- a/Specs/Core/GeometryPipelineSpec.js +++ b/Specs/Core/GeometryPipelineSpec.js @@ -38,6 +38,7 @@ defineSuite([ it('converts triangles to wireframe in place', function() { var geometry = GeometryPipeline.toWireframe(new Geometry({ + attributes : {}, indices : [0, 1, 2, 3, 4, 5], primitiveType : PrimitiveType.TRIANGLES })); @@ -64,6 +65,7 @@ defineSuite([ it('converts a triangle fan to wireframe in place', function() { var geometry = GeometryPipeline.toWireframe(new Geometry({ + attributes : {}, indices : [0, 1, 2, 3], primitiveType : PrimitiveType.TRIANGLE_FAN })); @@ -90,6 +92,7 @@ defineSuite([ it('converts a triangle strip to wireframe in place', function() { var geometry = GeometryPipeline.toWireframe(new Geometry({ + attributes : {}, indices : [0, 1, 2, 3], primitiveType : PrimitiveType.TRIANGLE_STRIP })); @@ -180,10 +183,23 @@ defineSuite([ it('creates attribute indices', function() { var geometry = new Geometry({ attributes : { - position : new GeometryAttribute(), - normal : new GeometryAttribute(), - color : new GeometryAttribute() - } + position : new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : [] + }), + normal : new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : [] + }), + color : new GeometryAttribute({ + componentDatatype : ComponentDatatype.UNSIGNED_BYTE, + componentsPerAttribute : 4, + values : [] + }) + }, + primitiveType : PrimitiveType.TRIANGLES }); var indices = GeometryPipeline.createAttributeIndices(geometry); @@ -569,7 +585,8 @@ defineSuite([ componentsPerAttribute : 3, values : [c.x, c.y, c.z] }) - } + }, + primitiveType : PrimitiveType.POINTS }); geometry = GeometryPipeline.encodeAttribute(geometry); @@ -715,7 +732,8 @@ defineSuite([ componentsPerAttribute : 3, values : [0.0, 0.0, 0.0] }) - } + }, + primitiveType : PrimitiveType.POINTS }) }); @@ -732,7 +750,8 @@ defineSuite([ componentsPerAttribute : 3, values : [0.0, 0.0, 0.0] }) - } + }, + primitiveType : PrimitiveType.POINTS }) }); var anotherInstance = new GeometryInstance({ @@ -743,7 +762,8 @@ defineSuite([ componentsPerAttribute : 3, values : [1.0, 1.0, 1.0] }) - } + }, + primitiveType : PrimitiveType.POINTS }) }); @@ -758,7 +778,8 @@ defineSuite([ 1.0, 1.0, 1.0 ]) }) - } + }, + primitiveType : PrimitiveType.POINTS })); }); @@ -886,26 +907,28 @@ defineSuite([ it('combine throws when instances.modelMatrix do not match', function() { var instance0 = new GeometryInstance({ geometry : new Geometry({ - attributes : new GeometryAttribute({ - position : { + attributes : { + position : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 3, values : [0.0, 0.0, 0.0] - } - }) + }) + }, + primitiveType : PrimitiveType.POINTS }), modelMatrix : Matrix4.fromScale(new Cartesian3(1.0, 1.0, 1.0)) }); var instance1 = new GeometryInstance({ geometry : new Geometry({ - attributes : new GeometryAttribute({ - position : { + attributes : { + position : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 3, values : [0.0, 0.0, 0.0] - } - }) + }) + }, + primitiveType : PrimitiveType.POINTS }), modelMatrix : Matrix4.fromScale(new Cartesian3(2.0, 2.0, 2.0)) }); @@ -918,26 +941,28 @@ defineSuite([ it('combine throws when instance geometries do not all have or not have an indices', function() { var instance0 = new GeometryInstance({ geometry : new Geometry({ - attributes : new GeometryAttribute({ - position : { + attributes : { + position : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 3, values : [0.0, 0.0, 0.0] - } - }), - indices : [0] + }) + }, + indices : [0], + primitiveType : PrimitiveType.POINTS }) }); var instance1 = new GeometryInstance({ geometry : new Geometry({ - attributes : new GeometryAttribute({ - position : { + attributes : { + position : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 3, values : [0.0, 0.0, 0.0] - } - }) + }) + }, + primitiveType : PrimitiveType.POINTS }) }); @@ -949,26 +974,26 @@ defineSuite([ it('combine throws when instance geometries do not all have the same primitive type', function() { var instance0 = new GeometryInstance({ geometry : new Geometry({ - attributes : new GeometryAttribute({ - position : { + attributes : { + position : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 3, values : [0.0, 0.0, 0.0] - } - }), + }) + }, primitiveType : PrimitiveType.POINTS }) }); var instance1 = new GeometryInstance({ geometry : new Geometry({ - attributes : new GeometryAttribute({ - position : { + attributes : { + position : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 3, values : [0.0, 0.0, 0.0, 1.0, 0.0, 0.0] - } - }), + }) + }, primitiveType : PrimitiveType.LINES }) }); @@ -989,9 +1014,11 @@ defineSuite([ attributes: { position: new GeometryAttribute({ values: [0, 0, 0, 1, 0, 0, 0, 1, 0], - componentsPerAttribute: 3 + componentsPerAttribute: 3, + componentDatatype : ComponentDatatype.FLOAT }) - } + }, + primitiveType : PrimitiveType.POINTS }); geometry = GeometryPipeline.computeNormal(geometry); @@ -1004,7 +1031,8 @@ defineSuite([ attributes: { position: new GeometryAttribute({ values: [0, 0, 0, 1, 0, 0, 0, 1, 0], - componentsPerAttribute: 3 + componentsPerAttribute: 3, + componentDatatype : ComponentDatatype.FLOAT }) }, indices : [0, 1, 2], @@ -1022,7 +1050,8 @@ defineSuite([ attributes: { position: new GeometryAttribute({ values: [0, 0, 0, 1, 0, 0, 0, 1, 0], - componentsPerAttribute: 3 + componentsPerAttribute: 3, + componentDatatype : ComponentDatatype.FLOAT }) }, indices : [0, 1, 2], @@ -1040,7 +1069,8 @@ defineSuite([ attributes: { position: new GeometryAttribute({ values: [0, 0, 0, 1, 0, 1, 1, 1, 1, 2, 0, 0], - componentsPerAttribute: 3 + componentsPerAttribute: 3, + componentDatatype : ComponentDatatype.FLOAT }) }, indices : [0, 1, 2, 1, 3, 2], @@ -1067,7 +1097,8 @@ defineSuite([ attributes: { position: new GeometryAttribute({ values: [0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0], - componentsPerAttribute: 3 + componentsPerAttribute: 3, + componentDatatype : ComponentDatatype.FLOAT }) }, indices : [0, 1, 2, 3, 0, 2, 4, 0, 3, 4, 5, 0, 5, 6, 0, 6, 1, 0], @@ -1109,18 +1140,22 @@ defineSuite([ attributes: { position: new GeometryAttribute({ values: [0, 0, 0, 1, 0, 0, 0, 1, 0], - componentsPerAttribute: 3 + componentsPerAttribute: 3, + componentDatatype : ComponentDatatype.FLOAT }), normal: new GeometryAttribute({ values: [0, 0, 0, 1, 0, 0, 0, 1, 0], - componentsPerAttribute: 3 + componentsPerAttribute: 3, + componentDatatype : ComponentDatatype.FLOAT }), st: new GeometryAttribute({ values: [0, 1], - componentsPerAttribute: 2 + componentsPerAttribute: 2, + componentDatatype : ComponentDatatype.FLOAT }) - } + }, + primitiveType : PrimitiveType.POINTS }); geometry = GeometryPipeline.computeBinormalAndTangent(geometry); @@ -1134,17 +1169,20 @@ defineSuite([ attributes: { position: new GeometryAttribute({ values: [0, 0, 0, 1, 0, 0, 0, 1, 0], - componentsPerAttribute: 3 + componentsPerAttribute: 3, + componentDatatype : ComponentDatatype.FLOAT }), normal: new GeometryAttribute({ values: [0, 0, 0, 1, 0, 0, 0, 1, 0], - componentsPerAttribute: 3 + componentsPerAttribute: 3, + componentDatatype : ComponentDatatype.FLOAT }), st: new GeometryAttribute({ values: [0, 1], - componentsPerAttribute: 2 + componentsPerAttribute: 2, + componentDatatype : ComponentDatatype.FLOAT }) }, indices : [0, 1, 2], @@ -1162,11 +1200,13 @@ defineSuite([ attributes: { position: new GeometryAttribute({ values: [0, 0, 0, 1, 0, 0, 0, 1, 0], - componentsPerAttribute: 3 + componentsPerAttribute: 3, + componentDatatype : ComponentDatatype.FLOAT }), st: new GeometryAttribute({ values: [0, 0, 1, 0, 0, 1], - componentsPerAttribute: 2 + componentsPerAttribute: 2, + componentDatatype : ComponentDatatype.FLOAT }) }, indices : [0, 1, 2], @@ -1185,11 +1225,13 @@ defineSuite([ attributes: { position: new GeometryAttribute({ values: [0, 0, 0, 1, 0, 1, 1, 1, 1, 2, 0, 0], - componentsPerAttribute: 3 + componentsPerAttribute: 3, + componentDatatype : ComponentDatatype.FLOAT }), st: new GeometryAttribute({ values: [0, 0, 1, 0, 1, 1, 0, 1], - componentsPerAttribute: 2 + componentsPerAttribute: 2, + componentDatatype : ComponentDatatype.FLOAT }) }, indices : [0, 1, 2, 1, 3, 2], diff --git a/Specs/Core/GeometrySpec.js b/Specs/Core/GeometrySpec.js index 194dbb3e0492..ce41c563620f 100644 --- a/Specs/Core/GeometrySpec.js +++ b/Specs/Core/GeometrySpec.js @@ -44,139 +44,20 @@ defineSuite([ expect(geometry.boundingSphere).toBe(boundingSphere); }); - it('clone returns undefined when geometry is undefined', function() { - expect(Geometry.clone()).not.toBeDefined(); - }); - - it('clone', function() { - var attributes = { - position : new GeometryAttribute({ - componentDatatype : ComponentDatatype.DOUBLE, - componentsPerAttribute : 3, - values : new Float64Array([ - 0.0, 0.0, 0.0, - 1.0, 0.0, 0.0, - 0.0, 1.0, 0.0 - ]) - }), - st : new GeometryAttribute({ - componentDatatype : ComponentDatatype.FLOAT, - componentsPerAttribute : 2, - values : new Float32Array([ - 0.0, 0.0, - 1.0, 0.0, - 0.0, 1.0 - ]) - }) - }; - var indices = new Uint16Array([0, 1, 2]); - var boundingSphere = new BoundingSphere(new Cartesian3(0.5, 0.5, 0.0), 1.0); - - var geometry = new Geometry({ - attributes : attributes, - indices : indices, - primitiveType : PrimitiveType.TRIANGLES, - boundingSphere : boundingSphere - }); - var clone = Geometry.clone(geometry); - - expect(clone.attributes).not.toBe(geometry.attributes); - expect(clone.attributes.position).toBeDefined(); - expect(clone.attributes.st).toBeDefined(); - - expect(clone.indices).toBeDefined(); - expect(clone.indices).not.toBe(geometry.indices); - expect(clone.indices instanceof Uint16Array).toEqual(true); - - expect(clone.primitiveType).toEqual(geometry.primitiveType); - expect(clone.boundingSphere).toEqual(geometry.boundingSphere); - }); - - it('clone with undefined indices', function() { - var attributes = { - position : new GeometryAttribute({ - componentDatatype : ComponentDatatype.DOUBLE, - componentsPerAttribute : 3, - values : new Float64Array([ - 0.0, 0.0, 0.0, - 1.0, 0.0, 0.0, - 0.0, 1.0, 0.0 - ]) - }), - st : new GeometryAttribute({ - componentDatatype : ComponentDatatype.FLOAT, - componentsPerAttribute : 2, - values : new Float32Array([ - 0.0, 0.0, - 1.0, 0.0, - 0.0, 1.0 - ]) - }) - }; - var boundingSphere = new BoundingSphere(new Cartesian3(0.5, 0.5, 0.0), 1.0); - - var geometry = new Geometry({ - attributes : attributes, - primitiveType : PrimitiveType.TRIANGLES, - boundingSphere : boundingSphere - }); - var clone = Geometry.clone(geometry); - - expect(clone.attributes).not.toBe(geometry.attributes); - expect(clone.attributes.position).toBeDefined(); - expect(clone.attributes.st).toBeDefined(); - - expect(clone.indices).not.toBeDefined(); - - expect(clone.primitiveType).toEqual(geometry.primitiveType); - expect(clone.boundingSphere).toEqual(geometry.boundingSphere); + it('constructor thows without primitiveType', function() { + expect(function() { + return new Geometry({ + attributes : {} + }); + }).toThrow(); }); - it('clone with result parameter', function() { - var attributes = { - position : new GeometryAttribute({ - componentDatatype : ComponentDatatype.DOUBLE, - componentsPerAttribute : 3, - values : new Float64Array([ - 0.0, 0.0, 0.0, - 1.0, 0.0, 0.0, - 0.0, 1.0, 0.0 - ]) - }), - st : new GeometryAttribute({ - componentDatatype : ComponentDatatype.FLOAT, - componentsPerAttribute : 2, - values : new Float32Array([ - 0.0, 0.0, - 1.0, 0.0, - 0.0, 1.0 - ]) - }) - }; - var indices = new Uint16Array([0, 1, 2]); - var boundingSphere = new BoundingSphere(new Cartesian3(0.5, 0.5, 0.0), 1.0); - - var geometry = new Geometry({ - attributes : attributes, - indices : indices, - primitiveType : PrimitiveType.TRIANGLES, - boundingSphere : boundingSphere - }); - var result = new Geometry(); - var clone = Geometry.clone(geometry, result); - - expect(clone).toBe(result); - - expect(clone.attributes).not.toBe(geometry.attributes); - expect(clone.attributes.position).toBeDefined(); - expect(clone.attributes.st).toBeDefined(); - - expect(clone.indices).toBeDefined(); - expect(clone.indices).not.toBe(geometry.indices); - expect(clone.indices instanceof Uint16Array).toEqual(true); - - expect(clone.primitiveType).toEqual(geometry.primitiveType); - expect(clone.boundingSphere).toEqual(geometry.boundingSphere); + it('constructor throws without attributes', function() { + expect(function() { + return new Geometry({ + primitiveType : PrimitiveType.TRIANGLES + }); + }).toThrow(); }); it('computeNumberOfVertices', function() { diff --git a/Specs/Renderer/VertexArrayFactorySpec.js b/Specs/Renderer/VertexArrayFactorySpec.js index d8031063858b..c98a6122dbec 100644 --- a/Specs/Renderer/VertexArrayFactorySpec.js +++ b/Specs/Renderer/VertexArrayFactorySpec.js @@ -65,7 +65,8 @@ defineSuite([ componentsPerAttribute : 3, values : [0.0, 0.0, 0.0, 1.0, 1.0, 1.0] }) - } + }, + primitiveType : PrimitiveType.POINTS }); var va = context.createVertexArrayFromGeometry({ @@ -94,7 +95,8 @@ defineSuite([ componentsPerAttribute : 3, values : [0.0, 0.0, 0.0, 1.0, 1.0, 1.0] }) - } + }, + primitiveType : PrimitiveType.POINTS }); var va = context.createVertexArrayFromGeometry({ @@ -130,7 +132,8 @@ defineSuite([ componentsPerAttribute : 3, values : [1.0, 1.0, 1.0, 3.0, 3.0, 3.0] }) - } + }, + primitiveType : PrimitiveType.POINTS }); var va = context.createVertexArrayFromGeometry({ @@ -171,7 +174,8 @@ defineSuite([ componentsPerAttribute : 3, values : [1.0, 1.0, 1.0, 3.0, 3.0, 3.0] }) - } + }, + primitiveType : PrimitiveType.POINTS }); var va = context.createVertexArrayFromGeometry({ @@ -215,7 +219,8 @@ defineSuite([ componentsPerAttribute : 4, values : [1, 1, 1, 1, 2, 2, 2, 2] }) - } + }, + primitiveType : PrimitiveType.POINTS }); var va = context.createVertexArrayFromGeometry({ @@ -264,7 +269,8 @@ defineSuite([ componentsPerAttribute : 1, values : [2] }) - } + }, + primitiveType : PrimitiveType.POINTS }); var attributeIndices = GeometryPipeline.createAttributeIndices(geometry); @@ -324,7 +330,8 @@ defineSuite([ componentsPerAttribute : 3, values : [0.0, 0.0, 0.0, 0.0, 0.0, 0.0] }) - } + }, + primitiveType : PrimitiveType.POINTS }); var attributeIndices = GeometryPipeline.createAttributeIndices(geometry); @@ -398,7 +405,8 @@ defineSuite([ componentsPerAttribute : 1, values : [5] }) - } + }, + primitiveType : PrimitiveType.POINTS }); var attributeIndices = GeometryPipeline.createAttributeIndices(geometry); @@ -465,7 +473,8 @@ defineSuite([ componentsPerAttribute : 1, values : [75, 100] }) - } + }, + primitiveType : PrimitiveType.POINTS }); var attributeIndices = GeometryPipeline.createAttributeIndices(geometry); @@ -544,6 +553,7 @@ defineSuite([ it('creates an index buffer', function() { var geometry = new Geometry({ + attributes : {}, indices : [0], primitiveType : PrimitiveType.POINTS }); @@ -572,7 +582,8 @@ defineSuite([ componentsPerAttribute : 1, values : [1.0, 2.0] }) - } + }, + primitiveType : PrimitiveType.POINTS }); expect(function() { @@ -596,7 +607,8 @@ defineSuite([ componentsPerAttribute : 1, values : [1.0] }) - } + }, + primitiveType : PrimitiveType.POINTS }); expect(function() { diff --git a/Specs/Scene/ExtentPrimitiveSpec.js b/Specs/Scene/ExtentPrimitiveSpec.js index 8c7bfd0d4b60..f1c8b4a0030c 100644 --- a/Specs/Scene/ExtentPrimitiveSpec.js +++ b/Specs/Scene/ExtentPrimitiveSpec.js @@ -90,7 +90,7 @@ defineSuite([ }); it('gets the default granularity', function() { - expect(extent.granularity).toEqual(CesiumMath.toRadians(1.0)); + expect(extent.granularity).toEqual(CesiumMath.RADIANS_PER_DEGREE); }); it('renders', function() { diff --git a/Specs/Scene/GeometryRenderingSpec.js b/Specs/Scene/GeometryRenderingSpec.js index 2617f6d0e2c2..1708187048da 100644 --- a/Specs/Scene/GeometryRenderingSpec.js +++ b/Specs/Scene/GeometryRenderingSpec.js @@ -411,7 +411,7 @@ defineSuite([ instance = new GeometryInstance({ geometry : new EllipsoidGeometry({ vertexFormat : PerInstanceColorAppearance.FLAT_VERTEX_FORMAT, - ellipsoid : new Ellipsoid(1000000.0, 1000000.0, 500000.0) + radii : new Cartesian3(1000000.0, 1000000.0, 500000.0) }), modelMatrix : Matrix4.multiplyByTranslation(Transforms.eastNorthUpToFixedFrame( ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-100, 20))), new Cartesian3(0.0, 0.0, 1000000.0)), diff --git a/Specs/Scene/PolygonSpec.js b/Specs/Scene/PolygonSpec.js index 63bb0bba1dd9..c2746ada23de 100644 --- a/Specs/Scene/PolygonSpec.js +++ b/Specs/Scene/PolygonSpec.js @@ -183,7 +183,7 @@ defineSuite([ }); it('gets the default granularity', function() { - expect(polygon.granularity).toEqual(CesiumMath.toRadians(1.0)); + expect(polygon.granularity).toEqual(CesiumMath.RADIANS_PER_DEGREE); }); it('renders', function() { diff --git a/Specs/Scene/createTangentSpaceDebugPrimitiveSpec.js b/Specs/Scene/createTangentSpaceDebugPrimitiveSpec.js index c54a1e82e833..d07b428ebb03 100644 --- a/Specs/Scene/createTangentSpaceDebugPrimitiveSpec.js +++ b/Specs/Scene/createTangentSpaceDebugPrimitiveSpec.js @@ -22,7 +22,7 @@ defineSuite([ it('computes all attributes', function() { var geometry = new EllipsoidGeometry({ vertexFormat : VertexFormat.ALL, - ellipsoid : new Ellipsoid(500000.0, 500000.0, 1000000.0) + radii : new Cartesian3(500000.0, 500000.0, 1000000.0) }); var modelMatrix = Matrix4.multiplyByTranslation(Matrix4.IDENTITY, new Cartesian3(0.0, 0.0, 11000000.0)); From 8a5a62aaf38757ddb1ad3dc4bd139b4dd005b6e4 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Tue, 9 Jul 2013 19:02:48 -0400 Subject: [PATCH 297/306] More updates based on review. --- Source/Core/EllipsoidGeometry.js | 1 - Source/Core/GeometryInstanceAttribute.js | 6 +- Source/Core/GeometryPipeline.js | 397 +++++++++++--------- Source/Core/IndexDatatype.js | 8 +- Source/Core/Math.js | 8 +- Source/Renderer/Context.js | 4 +- Source/Renderer/VertexArrayFacade.js | 13 +- Source/Scene/PolylineCollection.js | 13 +- Specs/Core/GeometryInstanceAttributeSpec.js | 8 +- Specs/Core/GeometryPipelineSpec.js | 247 ++++++++++-- Specs/Scene/PolylineCollectionSpec.js | 10 +- 11 files changed, 474 insertions(+), 241 deletions(-) diff --git a/Source/Core/EllipsoidGeometry.js b/Source/Core/EllipsoidGeometry.js index 77900d691fea..861cd3ad1c70 100644 --- a/Source/Core/EllipsoidGeometry.js +++ b/Source/Core/EllipsoidGeometry.js @@ -216,7 +216,6 @@ define([ if (vertexFormat.position) { // Expand cube into ellipsoid and flatten values - var radii = ellipsoid.getRadii(); var flattenedPositions = new Float64Array(length * 3); for (i = j = 0; i < length; ++i) { diff --git a/Source/Core/GeometryInstanceAttribute.js b/Source/Core/GeometryInstanceAttribute.js index ef9ef7d833ca..3958dab12a44 100644 --- a/Source/Core/GeometryInstanceAttribute.js +++ b/Source/Core/GeometryInstanceAttribute.js @@ -1,8 +1,10 @@ /*global define*/ define([ - './defaultValue' + './defaultValue', + './DeveloperError' ], function( - defaultValue) { + defaultValue, + DeveloperError) { "use strict"; /** diff --git a/Source/Core/GeometryPipeline.js b/Source/Core/GeometryPipeline.js index 8f589b1375ea..88c9b9d5c8f2 100644 --- a/Source/Core/GeometryPipeline.js +++ b/Source/Core/GeometryPipeline.js @@ -48,7 +48,7 @@ define([ "use strict"; /** - * Content pipeline functions for geometries. These functions generally modify geometry in place. + * Content pipeline functions for geometries. * * @exports GeometryPipeline * @@ -126,11 +126,12 @@ define([ * This is commonly used to create a wireframe geometry for visual debugging. *

    * - * @param {Geometry} geometry The geometry to modify, which is modified in place. + * @param {Geometry} geometry The geometry to modify. * * @returns {Geometry} The modified geometry argument, with its triangle indices converted to lines. * * @exception {DeveloperError} geometry is required. + * @exception {DeveloperError} geometry.primitiveType must be TRIANGLES, TRIANGLE_STRIP, or TRIANGLE_FAN. * * @example * geometry = GeometryPipeline.toWireframe(geometry); @@ -152,6 +153,8 @@ define([ case PrimitiveType.TRIANGLE_FAN: geometry.indices = triangleFanToLines(indices); break; + default: + throw new DeveloperError('geometry.primitiveType must be TRIANGLES, TRIANGLE_STRIP, or TRIANGLE_FAN.'); } geometry.primitiveType = PrimitiveType.LINES; @@ -189,7 +192,7 @@ define([ attributeName = defaultValue(attributeName, 'normal'); - if (typeof geometry.attributes[attributeName] === 'defined') { + if (typeof geometry.attributes[attributeName] === 'undefined') { throw new DeveloperError('geometry.attributes must have an attribute with the same name as the attributeName parameter, ' + attributeName + '.'); } @@ -308,7 +311,7 @@ define([ /** * Reorders a geometry's attributes and indices to achieve better performance from the GPU's pre-vertex-shader cache. * - * @param {Geometry} geometry The geometry to modify, which is modified in place. + * @param {Geometry} geometry The geometry to modify. * * @returns {Geometry} The modified geometry argument, with its attributes and indices reordered for the GPU's pre-vertex-shader cache. * @@ -391,7 +394,7 @@ define([ * post vertex-shader cache by using the Tipsify algorithm. If the geometry primitiveType * is not TRIANGLES or the geometry does not have an indices, this function has no effect. * - * @param {Geometry} geometry The geometry to modify, which is modified in place. + * @param {Geometry} geometry The geometry to modify. * @param {Number} [cacheCapacity=24] The number of vertices that can be held in the GPU's vertex cache. * * @returns {Geometry} The modified geometry argument, with its indices reordered for the post-vertex-shader cache. @@ -435,7 +438,10 @@ define([ var newAttributes = {}; for ( var attribute in attributes) { - if (attributes.hasOwnProperty(attribute) && attributes[attribute].values) { + if (attributes.hasOwnProperty(attribute) && + typeof attributes[attribute] !== 'undefined' && + typeof attributes[attribute].values !== 'undefined') { + var attr = attributes[attribute]; newAttributes[attribute] = new GeometryAttribute({ componentDatatype : attr.componentDatatype, @@ -451,7 +457,10 @@ define([ function copyVertex(destinationAttributes, sourceAttributes, index) { for ( var attribute in sourceAttributes) { - if (sourceAttributes.hasOwnProperty(attribute) && sourceAttributes[attribute].values) { + if (sourceAttributes.hasOwnProperty(attribute) && + typeof sourceAttributes[attribute] !== 'undefined' && + typeof sourceAttributes[attribute].values !== 'undefined') { + var attr = sourceAttributes[attribute]; for ( var k = 0; k < attr.componentsPerAttribute; ++k) { @@ -462,14 +471,14 @@ define([ } /** - * Splits a geometry into multiple geometries - if necessary - to ensure that indices in the + * Splits a geometry into multiple geometries, if necessary, to ensure that indices in the * indices fit into unsigned shorts. This is used to meet the WebGL requirements * when {@link Context#getElementIndexUint} is false. *

    - * If the geometry does not have an indices, this function has no effect. + * If the geometry does not have any indices, this function has no effect. *

    * - * @param {Geometry} geometry The geometry to modify, which is modified in place if it needs to be split into multiple geometries. + * @param {Geometry} geometry The geometry to be split into multiple geometries. * * @returns {Array} An array of geometries, each with indices that fit into unsigned shorts. * @@ -497,8 +506,7 @@ define([ // If there's an index list and more than 64K attributes, it is possible that // some indices are outside the range of unsigned short [0, 64K - 1] var numberOfVertices = Geometry.computeNumberOfVertices(geometry); - var sixtyFourK = 64 * 1024; - if (typeof geometry.indices !== 'undefined' && (numberOfVertices > sixtyFourK)) { + if (typeof geometry.indices !== 'undefined' && (numberOfVertices > CesiumMath.SIXTY_FOUR_KILOBYTES)) { var oldToNewIndex = []; var newIndices = []; var currentIndex = 0; @@ -529,7 +537,7 @@ define([ newIndices.push(i); } - if (currentIndex + indicesPerPrimitive > sixtyFourK) { + if (currentIndex + indicesPerPrimitive > CesiumMath.SIXTY_FOUR_KILOBYTES) { geometries.push(new Geometry({ attributes : newAttributes, indices : newIndices, @@ -571,7 +579,7 @@ define([ * If the geometry does not have a position, this function has no effect. *

    * - * @param {Geometry} geometry The geometry to modify, which is modified in place. + * @param {Geometry} geometry The geometry to modify. * @param {Object} [projection=new GeographicProjection()] The projection to use. * * @returns {Geometry} The modified geometry argument with position3D and position2D attributes. @@ -591,12 +599,12 @@ define([ var ellipsoid = projection.getEllipsoid(); // Project original positions to 2D. - var wgs84Positions = geometry.attributes.position.values; - var projectedPositions = new Float64Array(wgs84Positions.length); + var positions3D = geometry.attributes.position.values; + var projectedPositions = new Float64Array(positions3D.length); var index = 0; - for ( var i = 0; i < wgs84Positions.length; i += 3) { - var position = Cartesian3.fromArray(wgs84Positions, i, scratchProjectTo2DCartesian3); + for ( var i = 0; i < positions3D.length; i += 3) { + var position = Cartesian3.fromArray(positions3D, i, scratchProjectTo2DCartesian3); var lonLat = ellipsoid.cartesianToCartographic(position, scratchProjectTo2DCartographic); var projectedLonLat = projection.project(lonLat, scratchProjectTo2DCartesian3); @@ -632,14 +640,17 @@ define([ * This is commonly used to create high-precision position vertex attributes. *

    * - * @param {Geometry} geometry The geometry to modify, which is modified in place. - * @param {String} [attributeName='position'] The name of the attribute. - * @param {String} [attributeHighName='positionHigh'] The name of the attribute for the encoded high bits. - * @param {String} [attributeLowName='positionLow'] The name of the attribute for the encoded low bits. + * @param {Geometry} geometry The geometry to modify. + * @param {String} attributeName The name of the attribute. + * @param {String} attributeHighName The name of the attribute for the encoded high bits. + * @param {String} attributeLowName The name of the attribute for the encoded low bits. * * @returns {Geometry} The modified geometry argument, with its encoded attribute. * * @exception {DeveloperError} geometry is required. + * @exception {DeveloperError} attributeName is required. + * @exception {DeveloperError} attributeHighName is required. + * @exception {DeveloperError} attributeLowName is required. * @exception {DeveloperError} geometry must have attribute matching the attributeName argument. * @exception {DeveloperError} The attribute componentDatatype must be ComponentDatatype.DOUBLE. * @@ -649,14 +660,22 @@ define([ * @see EncodedCartesian3 */ GeometryPipeline.encodeAttribute = function(geometry, attributeName, attributeHighName, attributeLowName) { - attributeName = defaultValue(attributeName, 'position'); - attributeHighName = defaultValue(attributeHighName, 'positionHigh'); - attributeLowName = defaultValue(attributeLowName, 'positionLow'); - if (typeof geometry === 'undefined') { throw new DeveloperError('geometry is required.'); } + if (typeof attributeName === 'undefined') { + throw new DeveloperError('attributeName is required.'); + } + + if (typeof attributeHighName === 'undefined') { + throw new DeveloperError('attributeHighName is required.'); + } + + if (typeof attributeLowName === 'undefined') { + throw new DeveloperError('attributeLowName is required.'); + } + var attribute = geometry.attributes[attributeName]; if (typeof attribute === 'undefined') { @@ -735,7 +754,7 @@ define([ * following attributes if they are present: position, normal, * binormal, and tangent. * - * @param {GeometryInstance} instance The geometry instance to modify, which is modified in place. + * @param {GeometryInstance} instance The geometry instance to modify. * * @returns {GeometryInstance} The modified instance argument, with its attributes transforms to world coordinates. * @@ -852,7 +871,7 @@ define([ * * @param {Array} [instances] The array of {@link GeometryInstance} objects whose geometry will be combined. * - * @returns {Geometry} A new geometry created from the provided geometry instances. + * @returns {Geometry} A single geometry created from the provided geometry instances. * * @exception {DeveloperError} instances is required and must have length greater than zero. * @exception {DeveloperError} All instances must have the same modelMatrix. @@ -874,10 +893,6 @@ define([ var length = instances.length; - if (length === 1) { - return instances[0].geometry; - } - var name; var i; var j; @@ -991,17 +1006,16 @@ define([ * Computes per-vertex normals for a geometry containing TRIANGLES by averaging the normals of * all triangles incident to the vertex. The result is a new normal attribute added to the geometry. * This assumes a counter-clockwise winding order. - *

    - * This function has no effect if the geometry's indices is undefined or the - * primitiveType is not {@link PrimitiveType.TRIANGLES} or the geometry does not have a - * position attribute. - *

    * - * @param {Geometry} geometry The geometry to modify, which is modified in place. + * @param {Geometry} geometry The geometry to modify. * * @returns {Geometry} The modified geometry argument with the computed normal attribute. * - * @exception {DeveloperError} geometry is required + * @exception {DeveloperError} geometry is required. + * @exception {DeveloperError} geometry.attributes.position.values is required. + * @exception {DeveloperError} geometry.indices is required. + * @exception {DeveloperError} geometry.indices length must be greater than 0 and be a multiple of 3. + * @exception {DeveloperError} geometry.primitiveType must be {@link PrimitiveType.TRIANGLES}. * * @example * GeometryPipeline.computeNormal(geometry); @@ -1014,14 +1028,20 @@ define([ var attributes = geometry.attributes; var indices = geometry.indices; - if (typeof attributes.position === 'undefined' || - typeof attributes.position.values === 'undefined' || - geometry.primitiveType !== PrimitiveType.TRIANGLES || - typeof indices === 'undefined' || - indices.length < 2 || - indices.length % 3 !== 0) { + if (typeof attributes.position === 'undefined' || typeof attributes.position.values === 'undefined') { + throw new DeveloperError('geometry.attributes.position.values is required.'); + } - return geometry; + if (typeof indices === 'undefined') { + throw new DeveloperError('geometry.indices is required.'); + } + + if (indices.length < 2 || indices.length % 3 !== 0) { + throw new DeveloperError('geometry.indices length must be greater than 0 and be a multiple of 3.'); + } + + if (geometry.primitiveType !== PrimitiveType.TRIANGLES) { + throw new DeveloperError('geometry.primitiveType must be PrimitiveType.TRIANGLES.'); } var vertices = geometry.attributes.position.values; @@ -1031,7 +1051,7 @@ define([ var normalsPerTriangle = new Array(numIndices / 3); var normalIndices = new Array(numIndices); - for (var i = 0; i < numVertices; i++) { + for ( var i = 0; i < numVertices; i++) { normalsPerVertex[i] = { indexOffset : 0, count : 0, @@ -1044,9 +1064,9 @@ define([ var i0 = indices[i]; var i1 = indices[i + 1]; var i2 = indices[i + 2]; - var i03 = i0*3; - var i13 = i1*3; - var i23 = i2*3; + var i03 = i0 * 3; + var i13 = i1 * 3; + var i23 = i2 * 3; v0.x = vertices[i03]; v0.y = vertices[i03 + 1]; @@ -1116,9 +1136,9 @@ define([ } geometry.attributes.normal = new GeometryAttribute({ - componentDatatype: ComponentDatatype.FLOAT, - componentsPerAttribute: 3, - values: normalValues + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3, + values : normalValues }); return geometry; @@ -1133,20 +1153,21 @@ define([ * The result is new binormal and tangent attributes added to the geometry. * This assumes a counter-clockwise winding order. *

    - * This function has no effect if the geometry's indices is undefined or the - * primitiveType is not {@link PrimitiveType.TRIANGLES} or the geometry does not have - * position, normal, and st attributes. - *

    - *

    * Based on Computing Tangent Space Basis Vectors * for an Arbitrary Mesh by Eric Lengyel. *

    * - * @param {Geometry} geometry The geometry to modify, which is modified in place. + * @param {Geometry} geometry The geometry to modify. * * @returns {Geometry} The modified geometry argument with the computed binormal and tangent attributes. * * @exception {DeveloperError} geometry is required. + * @exception {DeveloperError} geometry.attributes.position.values is required. + * @exception {DeveloperError} geometry.attributes.normal.values is required. + * @exception {DeveloperError} geometry.attributes.st.values is required. + * @exception {DeveloperError} geometry.indices is required. + * @exception {DeveloperError} geometry.indices length must be greater than 0 and be a multiple of 3. + * @exception {DeveloperError} geometry.primitiveType must be {@link PrimitiveType.TRIANGLES}. * * @example * GeometryPipeline.computeBinormalAndTangent(geometry); @@ -1157,43 +1178,57 @@ define([ } var attributes = geometry.attributes; - var vertices = geometry.attributes.position.values; - var normals = geometry.attributes.normal.values; - var st = geometry.attributes.st.values; var indices = geometry.indices; - if ((typeof attributes.position === 'undefined' || typeof attributes.position.values === 'undefined') || - (typeof attributes.normal === 'undefined' || typeof attributes.normal.values === 'undefined') || - (typeof attributes.st === 'undefined' || typeof attributes.st.values === 'undefined') || - geometry.primitiveType !== PrimitiveType.TRIANGLES || - typeof indices === 'undefined' || - indices.length < 2 || - indices.length % 3 !== 0) { + if (typeof attributes.position === 'undefined' || typeof attributes.position.values === 'undefined') { + throw new DeveloperError('geometry.attributes.position.values is required.'); + } + + if (typeof attributes.normal === 'undefined' || typeof attributes.normal.values === 'undefined') { + throw new DeveloperError('geometry.attributes.normal.values is required.'); + } - return geometry; + if (typeof attributes.st === 'undefined' || typeof attributes.st.values === 'undefined') { + throw new DeveloperError('geometry.attributes.st.values is required.'); + } + + if (typeof indices === 'undefined') { + throw new DeveloperError('geometry.indices is required.'); + } + + if (indices.length < 2 || indices.length % 3 !== 0) { + throw new DeveloperError('geometry.indices length must be greater than 0 and be a multiple of 3.'); + } + + if (geometry.primitiveType !== PrimitiveType.TRIANGLES) { + throw new DeveloperError('geometry.primitiveType must be PrimitiveType.TRIANGLES.'); } - var numVertices = geometry.attributes.position.values.length/3; + var vertices = geometry.attributes.position.values; + var normals = geometry.attributes.normal.values; + var st = geometry.attributes.st.values; + + var numVertices = geometry.attributes.position.values.length / 3; var numIndices = indices.length; var tan1 = new Array(numVertices * 3); - for (var i = 0; i < tan1.length; i++) { + for ( var i = 0; i < tan1.length; i++) { tan1[i] = 0; } var i03; var i13; var i23; - for (i = 0; i < numIndices; i+=3) { + for (i = 0; i < numIndices; i += 3) { var i0 = indices[i]; var i1 = indices[i + 1]; var i2 = indices[i + 2]; - i03 = i0*3; - i13 = i1*3; - i23 = i2*3; - var i02 = i0*2; - var i12 = i1*2; - var i22 = i2*2; + i03 = i0 * 3; + i13 = i1 * 3; + i23 = i2 * 3; + var i02 = i0 * 2; + var i12 = i1 * 2; + var i22 = i2 * 2; var ux = vertices[i03]; var uy = vertices[i03 + 1]; @@ -1210,16 +1245,16 @@ define([ var sdirz = (t2 * (vertices[i13 + 2] - uz) - t1 * (vertices[i23 + 2] - uz)) * r; tan1[i03] += sdirx; - tan1[i03+1] += sdiry; - tan1[i03+2] += sdirz; + tan1[i03 + 1] += sdiry; + tan1[i03 + 2] += sdirz; tan1[i13] += sdirx; - tan1[i13+1] += sdiry; - tan1[i13+2] += sdirz; + tan1[i13 + 1] += sdiry; + tan1[i13 + 2] += sdirz; tan1[i23] += sdirx; - tan1[i23+1] += sdiry; - tan1[i23+2] += sdirz; + tan1[i23 + 1] += sdiry; + tan1[i23 + 2] += sdirz; } var binormalValues = new Float32Array(numVertices * 3); @@ -1463,106 +1498,106 @@ define([ // In WGS84 coordinates, for a triangle approximately on the // ellipsoid to cross the IDL, first it needs to be on the // negative side of the plane x = 0. - if ((p0.x < 0.0) && (p1.x < 0.0) && (p2.x < 0.0)) { - var p0Behind = p0.y < 0.0; - var p1Behind = p1.y < 0.0; - var p2Behind = p2.y < 0.0; - - offsetPointFromXZPlane(p0, p0Behind); - offsetPointFromXZPlane(p1, p1Behind); - offsetPointFromXZPlane(p2, p2Behind); - - var numBehind = 0; - numBehind += p0Behind ? 1 : 0; - numBehind += p1Behind ? 1 : 0; - numBehind += p2Behind ? 1 : 0; - - var indices = splitTriangleResult.indices; - - if (numBehind === 1) { - indices[1] = 3; - indices[2] = 4; - indices[5] = 6; - indices[7] = 6; - indices[8] = 5; - - if (p0Behind) { - getXZIntersectionOffsetPoints(p0, p1, u1, q1); - getXZIntersectionOffsetPoints(p0, p2, u2, q2); - - indices[0] = 0; - indices[3] = 1; - indices[4] = 2; - indices[6] = 1; - } else if (p1Behind) { - getXZIntersectionOffsetPoints(p1, p0, u1, q1); - getXZIntersectionOffsetPoints(p1, p2, u2, q2); - - indices[0] = 1; - indices[3] = 2; - indices[4] = 0; - indices[6] = 2; - } else if (p2Behind) { - getXZIntersectionOffsetPoints(p2, p0, u1, q1); - getXZIntersectionOffsetPoints(p2, p1, u2, q2); - - indices[0] = 2; - indices[3] = 0; - indices[4] = 1; - indices[6] = 0; - } - } else if (numBehind === 2) { - indices[2] = 4; - indices[4] = 4; - indices[5] = 3; - indices[7] = 5; - indices[8] = 6; - - if (!p0Behind) { - getXZIntersectionOffsetPoints(p0, p1, u1, q1); - getXZIntersectionOffsetPoints(p0, p2, u2, q2); - - indices[0] = 1; - indices[1] = 2; - indices[3] = 1; - indices[6] = 0; - } else if (!p1Behind) { - getXZIntersectionOffsetPoints(p1, p2, u1, q1); - getXZIntersectionOffsetPoints(p1, p0, u2, q2); - - indices[0] = 2; - indices[1] = 0; - indices[3] = 2; - indices[6] = 1; - } else if (!p2Behind) { - getXZIntersectionOffsetPoints(p2, p0, u1, q1); - getXZIntersectionOffsetPoints(p2, p1, u2, q2); - - indices[0] = 0; - indices[1] = 1; - indices[3] = 0; - indices[6] = 2; - } + if ((p0.x >= 0.0) || (p1.x >= 0.0) || (p2.x >= 0.0)) { + return undefined; + } + + var p0Behind = p0.y < 0.0; + var p1Behind = p1.y < 0.0; + var p2Behind = p2.y < 0.0; + + offsetPointFromXZPlane(p0, p0Behind); + offsetPointFromXZPlane(p1, p1Behind); + offsetPointFromXZPlane(p2, p2Behind); + + var numBehind = 0; + numBehind += p0Behind ? 1 : 0; + numBehind += p1Behind ? 1 : 0; + numBehind += p2Behind ? 1 : 0; + + var indices = splitTriangleResult.indices; + + if (numBehind === 1) { + indices[1] = 3; + indices[2] = 4; + indices[5] = 6; + indices[7] = 6; + indices[8] = 5; + + if (p0Behind) { + getXZIntersectionOffsetPoints(p0, p1, u1, q1); + getXZIntersectionOffsetPoints(p0, p2, u2, q2); + + indices[0] = 0; + indices[3] = 1; + indices[4] = 2; + indices[6] = 1; + } else if (p1Behind) { + getXZIntersectionOffsetPoints(p1, p0, u1, q1); + getXZIntersectionOffsetPoints(p1, p2, u2, q2); + + indices[0] = 1; + indices[3] = 2; + indices[4] = 0; + indices[6] = 2; + } else if (p2Behind) { + getXZIntersectionOffsetPoints(p2, p0, u1, q1); + getXZIntersectionOffsetPoints(p2, p1, u2, q2); + + indices[0] = 2; + indices[3] = 0; + indices[4] = 1; + indices[6] = 0; } - - var positions = splitTriangleResult.positions; - positions[0] = p0; - positions[1] = p1; - positions[2] = p2; - splitTriangleResult.length = 3; - - if (numBehind === 1 || numBehind === 2) { - positions[3] = u1; - positions[4] = u2; - positions[5] = q1; - positions[6] = q2; - splitTriangleResult.length = 7; + } else if (numBehind === 2) { + indices[2] = 4; + indices[4] = 4; + indices[5] = 3; + indices[7] = 5; + indices[8] = 6; + + if (!p0Behind) { + getXZIntersectionOffsetPoints(p0, p1, u1, q1); + getXZIntersectionOffsetPoints(p0, p2, u2, q2); + + indices[0] = 1; + indices[1] = 2; + indices[3] = 1; + indices[6] = 0; + } else if (!p1Behind) { + getXZIntersectionOffsetPoints(p1, p2, u1, q1); + getXZIntersectionOffsetPoints(p1, p0, u2, q2); + + indices[0] = 2; + indices[1] = 0; + indices[3] = 2; + indices[6] = 1; + } else if (!p2Behind) { + getXZIntersectionOffsetPoints(p2, p0, u1, q1); + getXZIntersectionOffsetPoints(p2, p1, u2, q2); + + indices[0] = 0; + indices[1] = 1; + indices[3] = 0; + indices[6] = 2; } + } + + var positions = splitTriangleResult.positions; + positions[0] = p0; + positions[1] = p1; + positions[2] = p2; + splitTriangleResult.length = 3; - return splitTriangleResult; + if (numBehind === 1 || numBehind === 2) { + positions[3] = u1; + positions[4] = u2; + positions[5] = q1; + positions[6] = q2; + splitTriangleResult.length = 7; } - return undefined; + return splitTriangleResult; } function computeTriangleAttributes(i0, i1, i2, dividedTriangle, normals, binormals, tangents, texCoords) { @@ -1815,7 +1850,7 @@ define([ * -180/180 degrees. This is not required for 3D drawing, but is required for * correcting drawing in 2D and Columbus view. * - * @param {Geometry} geometry The geometry to modify, which is modified in place. + * @param {Geometry} geometry The geometry to modify. * * @returns {Geometry} The modified geometry argument, with it's primitives split at the International Date Line. * diff --git a/Source/Core/IndexDatatype.js b/Source/Core/IndexDatatype.js index 298f3c7ed844..b32c8c7f5678 100644 --- a/Source/Core/IndexDatatype.js +++ b/Source/Core/IndexDatatype.js @@ -1,10 +1,12 @@ /*global define*/ define([ './Enumeration', - './DeveloperError' + './DeveloperError', + './Math' ], function( Enumeration, - DeveloperError) { + DeveloperError, + CesiumMath) { "use strict"; /** @@ -88,7 +90,7 @@ define([ throw new DeveloperError('numberOfVertices is required.'); } - if (numberOfVertices > 64 * 1024) { + if (numberOfVertices > CesiumMath.SIXTY_FOUR_KILOBYTES) { return new Uint32Array(indicesLengthOrArray); } diff --git a/Source/Core/Math.js b/Source/Core/Math.js index d5939acfedf5..3e304ad8fbfa 100644 --- a/Source/Core/Math.js +++ b/Source/Core/Math.js @@ -164,10 +164,16 @@ define([ * Radius of the sun in meters: 6.995e8 * @type {Number} * @constant - * @default */ CesiumMath.SOLAR_RADIUS = 6.995e8; + /** + * 64 * 1024 + * @type {Number} + * @constant + */ + CesiumMath.SIXTY_FOUR_KILOBYTES = 64 * 1024; + /** * Returns the sign of the value; 1 if the value is positive, -1 if the value is * negative, or 0 if the value is 0. diff --git a/Source/Renderer/Context.js b/Source/Renderer/Context.js index afe700d5ebbc..9fb8864ba3b9 100644 --- a/Source/Renderer/Context.js +++ b/Source/Renderer/Context.js @@ -11,6 +11,7 @@ define([ '../Core/Geometry', '../Core/createGuid', '../Core/Matrix4', + '../Core/Math', './Buffer', './BufferUsage', './CubeMap', @@ -45,6 +46,7 @@ define([ Geometry, createGuid, Matrix4, + CesiumMath, Buffer, BufferUsage, CubeMap, @@ -2448,7 +2450,7 @@ define([ var indexBuffer; var indices = geometry.indices; if (typeof indices !== 'undefined') { - if ((Geometry.computeNumberOfVertices(geometry) > 64 * 1024) && this.getElementIndexUint()) { + if ((Geometry.computeNumberOfVertices(geometry) > CesiumMath.SIXTY_FOUR_KILOBYTES) && this.getElementIndexUint()) { indexBuffer = this.createIndexBuffer(new Uint32Array(indices), bufferUsage, IndexDatatype.UNSIGNED_INT); } else{ indexBuffer = this.createIndexBuffer(new Uint16Array(indices), bufferUsage, IndexDatatype.UNSIGNED_SHORT); diff --git a/Source/Renderer/VertexArrayFacade.js b/Source/Renderer/VertexArrayFacade.js index 00d587a4fb7f..223b06e6d0bd 100644 --- a/Source/Renderer/VertexArrayFacade.js +++ b/Source/Renderer/VertexArrayFacade.js @@ -4,12 +4,14 @@ define([ '../Core/defaultValue', '../Core/destroyObject', '../Core/DeveloperError', + '../Core/Math', './BufferUsage' ], function( ComponentDatatype, defaultValue, destroyObject, DeveloperError, + CesiumMath, BufferUsage) { "use strict"; @@ -371,9 +373,6 @@ define([ } }; - // Using unsigned short indices, 64K vertices can be indexed by one index buffer - var sixtyFourK = 64 * 1024; - /** * DOC_TBA * @@ -403,7 +402,7 @@ define([ var buffersByUsage = buffersByPurposeAndUsage[purpose]; var va = []; - var numberOfVertexArrays = Math.ceil(this._size / sixtyFourK); + var numberOfVertexArrays = Math.ceil(this._size / CesiumMath.SIXTY_FOUR_KILOBYTES); for ( var k = 0; k < numberOfVertexArrays; ++k) { var attributes = []; @@ -413,7 +412,7 @@ define([ for (var allPurposeUsage in allPurposeBuffersByUsage) { if (allPurposeBuffersByUsage.hasOwnProperty(allPurposeUsage)) { var allPurposeBuffer = allPurposeBuffersByUsage[allPurposeUsage]; - VertexArrayFacade._appendAttributes(attributes, allPurposeBuffer, k * (allPurposeBuffer.vertexSizeInBytes * sixtyFourK)); + VertexArrayFacade._appendAttributes(attributes, allPurposeBuffer, k * (allPurposeBuffer.vertexSizeInBytes * CesiumMath.SIXTY_FOUR_KILOBYTES)); } } } @@ -422,7 +421,7 @@ define([ for (var usage in buffersByUsage) { if (buffersByUsage.hasOwnProperty(usage)) { buffer = buffersByUsage[usage]; - VertexArrayFacade._appendAttributes(attributes, buffer, k * (buffer.vertexSizeInBytes * sixtyFourK)); + VertexArrayFacade._appendAttributes(attributes, buffer, k * (buffer.vertexSizeInBytes * CesiumMath.SIXTY_FOUR_KILOBYTES)); } } @@ -430,7 +429,7 @@ define([ va.push({ va : this._context.createVertexArray(attributes, indexBuffer), - indicesCount : 1.5 * ((k !== (numberOfVertexArrays - 1)) ? sixtyFourK : (this._size % sixtyFourK)) + indicesCount : 1.5 * ((k !== (numberOfVertexArrays - 1)) ? CesiumMath.SIXTY_FOUR_KILOBYTES : (this._size % CesiumMath.SIXTY_FOUR_KILOBYTES)) // TODO: not hardcode 1.5 }); } diff --git a/Source/Scene/PolylineCollection.js b/Source/Scene/PolylineCollection.js index 08f4a448cbba..d4a2cace2a48 100644 --- a/Source/Scene/PolylineCollection.js +++ b/Source/Scene/PolylineCollection.js @@ -8,6 +8,7 @@ define([ '../Core/Cartesian4', '../Core/EncodedCartesian3', '../Core/Matrix4', + '../Core/Math', '../Core/ComponentDatatype', '../Core/IndexDatatype', '../Core/PrimitiveType', @@ -32,6 +33,7 @@ define([ Cartesian4, EncodedCartesian3, Matrix4, + CesiumMath, ComponentDatatype, IndexDatatype, PrimitiveType, @@ -57,7 +59,6 @@ define([ //When it does, we need to recreate the indicesBuffer. var POSITION_SIZE_INDEX = Polyline.POSITION_SIZE_INDEX; var NUMBER_OF_PROPERTIES = Polyline.NUMBER_OF_PROPERTIES; - var SIXTYFOURK = 64 * 1024; var attributeIndices = { position3DHigh : 0, @@ -744,14 +745,14 @@ define([ vbo += vertexBufferOffset[k]; - var positionHighOffset = 6 * (k * (positionSizeInBytes * SIXTYFOURK) - vbo * positionSizeInBytes);//componentsPerAttribute(3) * componentDatatype(4) + var positionHighOffset = 6 * (k * (positionSizeInBytes * CesiumMath.SIXTY_FOUR_KILOBYTES) - vbo * positionSizeInBytes);//componentsPerAttribute(3) * componentDatatype(4) var positionLowOffset = positionSizeInBytes + positionHighOffset; var prevPositionHighOffset = positionSizeInBytes + positionLowOffset; var prevPositionLowOffset = positionSizeInBytes + prevPositionHighOffset; var nextPositionHighOffset = positionSizeInBytes + prevPositionLowOffset; var nextPositionLowOffset = positionSizeInBytes + nextPositionHighOffset; - var vertexPickColorBufferOffset = k * (pickColorSizeInBytes * SIXTYFOURK) - vbo * pickColorSizeInBytes; - var vertexTexCoordExpandWidthAndShowBufferOffset = k * (texCoordExpandWidthAndShowSizeInBytes * SIXTYFOURK) - vbo * texCoordExpandWidthAndShowSizeInBytes; + var vertexPickColorBufferOffset = k * (pickColorSizeInBytes * CesiumMath.SIXTY_FOUR_KILOBYTES) - vbo * pickColorSizeInBytes; + var vertexTexCoordExpandWidthAndShowBufferOffset = k * (texCoordExpandWidthAndShowSizeInBytes * CesiumMath.SIXTY_FOUR_KILOBYTES) - vbo * texCoordExpandWidthAndShowSizeInBytes; var attributes = [{ index : attributeIndices.position3DHigh, @@ -1247,7 +1248,7 @@ define([ for ( var j = 0; j < numberOfSegments; ++j) { var segmentLength = segments[j] - 1.0; for ( var k = 0; k < segmentLength; ++k) { - if (indicesCount + 4 >= SIXTYFOURK - 1) { + if (indicesCount + 4 >= CesiumMath.SIXTY_FOUR_KILOBYTES - 1) { polyline._locatorBuckets.push({ locator : bucketLocator, count : segmentIndexCount @@ -1279,7 +1280,7 @@ define([ count : segmentIndexCount }); - if (indicesCount + 4 >= SIXTYFOURK - 1) { + if (indicesCount + 4 >= CesiumMath.SIXTY_FOUR_KILOBYTES - 1) { vertexBufferOffset.push(0); indices = []; totalIndices.push(indices); diff --git a/Specs/Core/GeometryInstanceAttributeSpec.js b/Specs/Core/GeometryInstanceAttributeSpec.js index 32bdfa941679..230286618ed1 100644 --- a/Specs/Core/GeometryInstanceAttributeSpec.js +++ b/Specs/Core/GeometryInstanceAttributeSpec.js @@ -24,7 +24,7 @@ defineSuite([ it('constructor throws without componentDatatype', function() { expect(function() { - return new GeometryAttribute({ + return new GeometryInstanceAttribute({ componentsPerAttribute : 4, value : new Uint8Array([255, 255, 0, 255]) }); @@ -33,7 +33,7 @@ defineSuite([ it('constructor throws without componentsPerAttribute', function() { expect(function() { - return new GeometryAttribute({ + return new GeometryInstanceAttribute({ componentDatatype : ComponentDatatype.UNSIGNED_BYTE, value : new Uint8Array([255, 255, 0, 255]) }); @@ -42,7 +42,7 @@ defineSuite([ it('constructor throws when componentsPerAttribute is less than 1 or greater than 4', function() { expect(function() { - return new GeometryAttribute({ + return new GeometryInstanceAttribute({ componentDatatype : ComponentDatatype.UNSIGNED_BYTE, componentsPerAttribute : 7, value : new Uint8Array([255, 255, 0, 255]) @@ -52,7 +52,7 @@ defineSuite([ it('constructor throws without values', function() { expect(function() { - return new GeometryAttribute({ + return new GeometryInstanceAttribute({ componentDatatype : ComponentDatatype.UNSIGNED_BYTE, componentsPerAttribute : 4 }); diff --git a/Specs/Core/GeometryPipelineSpec.js b/Specs/Core/GeometryPipelineSpec.js index 13893f372562..83ae56dfaaf4 100644 --- a/Specs/Core/GeometryPipelineSpec.js +++ b/Specs/Core/GeometryPipelineSpec.js @@ -123,6 +123,16 @@ defineSuite([ }).toThrow(); }); + it('toWireframe throws when primitiveType is not a triangle type', function() { + expect(function() { + GeometryPipeline.toWireframe(new Geometry({ + attributes : {}, + indices : [], + primitiveType : PrimitiveType.POINTS + })); + }).toThrow(); + }); + it('createLineSegmentsForVectors', function() { var geometry = new Geometry({ attributes : { @@ -163,7 +173,7 @@ defineSuite([ }).toThrow(); }); - it('createLineSegmentsForVectors throws when geometry.attributes does not vae an attributeName property', function() { + it('createLineSegmentsForVectors throws when geometry.attributes does not have an attributeName property', function() { var geometry = new Geometry({ attributes : { position : new GeometryAttribute({ @@ -351,7 +361,7 @@ defineSuite([ }); it('fitToUnsignedShortIndices creates one geometry', function() { - var sixtyFourK = 64 * 1024; + var sixtyFourK = CesiumMath.SIXTY_FOUR_KILOBYTES; var times = []; for ( var i = 0; i < sixtyFourK + 1; ++i) { times.push(i); @@ -381,7 +391,7 @@ defineSuite([ }); it('fitToUnsignedShortIndices creates two triangle geometries', function() { - var sixtyFourK = 64 * 1024; + var sixtyFourK = CesiumMath.SIXTY_FOUR_KILOBYTES; var positions = []; for ( var i = 0; i < sixtyFourK + 1; ++i) { @@ -418,7 +428,7 @@ defineSuite([ }); it('fitToUnsignedShortIndices creates two line geometries', function() { - var sixtyFourK = 64 * 1024; + var sixtyFourK = CesiumMath.SIXTY_FOUR_KILOBYTES; var positions = []; for ( var i = 0; i < sixtyFourK + 2; ++i) { @@ -455,7 +465,7 @@ defineSuite([ }); it('fitToUnsignedShortIndices creates two point geometries', function() { - var sixtyFourK = 64 * 1024; + var sixtyFourK = CesiumMath.SIXTY_FOUR_KILOBYTES; var positions = []; var indices = []; @@ -588,7 +598,7 @@ defineSuite([ }, primitiveType : PrimitiveType.POINTS }); - geometry = GeometryPipeline.encodeAttribute(geometry); + geometry = GeometryPipeline.encodeAttribute(geometry, 'position', 'positionHigh', 'positionLow'); expect(geometry.attributes.positionHigh).toBeDefined(); expect(geometry.attributes.positionHigh.values[0]).toEqual(encoded.high.x); @@ -607,15 +617,63 @@ defineSuite([ }).toThrow(); }); - it('encodeAttribute throws with geometry without attributes property', function() { + it('encodeAttribute throws without attributeName', function() { expect(function() { - GeometryPipeline.encodeAttribute({}); + GeometryPipeline.encodeAttribute(new Geometry({ + attributes : { + position : new GeometryAttribute({ + componentDatatype : ComponentDatatype.DOUBLE, + componentsPerAttribute : 3, + values : [0.0, 0.0, 0.0] + }) + }, + primitiveType : PrimitiveType.POINTS + })); + }).toThrow(); + }); + + it('encodeAttribute throws without attributeHighName', function() { + expect(function() { + GeometryPipeline.encodeAttribute(new Geometry({ + attributes : { + position : new GeometryAttribute({ + componentDatatype : ComponentDatatype.DOUBLE, + componentsPerAttribute : 3, + values : [0.0, 0.0, 0.0] + }) + }, + primitiveType : PrimitiveType.POINTS + }), 'position'); + }).toThrow(); + }); + + it('encodeAttribute throws without attributeLowName', function() { + expect(function() { + GeometryPipeline.encodeAttribute(new Geometry({ + attributes : { + position : new GeometryAttribute({ + componentDatatype : ComponentDatatype.DOUBLE, + componentsPerAttribute : 3, + values : [0.0, 0.0, 0.0] + }) + }, + primitiveType : PrimitiveType.POINTS + }), 'position', 'positionHigh'); }).toThrow(); }); it('encodeAttribute throws without attribute', function() { expect(function() { - GeometryPipeline.encodeAttribute(new Geometry()); + GeometryPipeline.encodeAttribute(new Geometry({ + attributes : { + position : new GeometryAttribute({ + componentDatatype : ComponentDatatype.DOUBLE, + componentsPerAttribute : 3, + values : [0.0, 0.0, 0.0] + }) + }, + primitiveType : PrimitiveType.POINTS + }), 'normal'); }).toThrow(); }); @@ -730,7 +788,7 @@ defineSuite([ position : new GeometryAttribute({ componentDatatype : ComponentDatatype.FLOAT, componentsPerAttribute : 3, - values : [0.0, 0.0, 0.0] + values : new Float32Array([0.0, 0.0, 0.0]) }) }, primitiveType : PrimitiveType.POINTS @@ -738,7 +796,7 @@ defineSuite([ }); var combined = GeometryPipeline.combine([instance]); - expect(combined).toBe(instance.geometry); + expect(combined).toEqual(instance.geometry); }); it('combine combines several geometries without indicess', function() { @@ -1009,7 +1067,18 @@ defineSuite([ }).toThrow(); }); - it('computeNormal does not compute normals when geometry.indices is undefined', function() { + it('computeNormal throws when geometry.attributes.position is undefined', function() { + var geometry = new Geometry({ + attributes: {}, + primitiveType : PrimitiveType.TRIANGLES + }); + + expect(function() { + GeometryPipeline.computeNormal(geometry); + }).toThrow(); + }); + + it('computeNormal throws when geometry.indices is undefined', function() { var geometry = new Geometry({ attributes: { position: new GeometryAttribute({ @@ -1018,15 +1087,32 @@ defineSuite([ componentDatatype : ComponentDatatype.FLOAT }) }, - primitiveType : PrimitiveType.POINTS + primitiveType : PrimitiveType.TRIANGLES }); - geometry = GeometryPipeline.computeNormal(geometry); + expect(function() { + GeometryPipeline.computeNormal(geometry); + }).toThrow(); + }); - expect(geometry.attributes.normal).not.toBeDefined(); + it('computeNormal throws when geometry.indices.length is not a multiple of 3', function() { + var geometry = new Geometry({ + attributes: { + position: new GeometryAttribute({ + values: [0, 0, 0, 1, 0, 0, 0, 1], + componentsPerAttribute: 3, + componentDatatype : ComponentDatatype.FLOAT + }) + }, + primitiveType : PrimitiveType.TRIANGLES + }); + + expect(function() { + GeometryPipeline.computeNormal(geometry); + }).toThrow(); }); - it('computeNormal does not compute normals when primitive type is not triangle', function() { + it('computeNormal throws when primitive type is not triangle', function() { var geometry = new Geometry({ attributes: { position: new GeometryAttribute({ @@ -1039,9 +1125,9 @@ defineSuite([ primitiveType: PrimitiveType.TRIANGLE_STRIP }); - geometry = GeometryPipeline.computeNormal(geometry); - - expect(geometry.attributes.normal).not.toBeDefined(); + expect(function() { + GeometryPipeline.computeNormal(geometry); + }).toThrow(); }); @@ -1135,7 +1221,80 @@ defineSuite([ }).toThrow(); }); - it('computeBinormalAndTangent does not compute tangent and binormals when geometry.indices is undefined', function() { + it('computeBinormalAndTangent throws when position is undefined', function() { + var geometry = new Geometry({ + attributes: { + normal: new GeometryAttribute({ + values: [0, 0, 0, 1, 0, 0, 0, 1, 0], + componentsPerAttribute: 3, + componentDatatype : ComponentDatatype.FLOAT + + }), + st: new GeometryAttribute({ + values: [0, 0, 1, 1], + componentsPerAttribute: 2, + componentDatatype : ComponentDatatype.FLOAT + }) + }, + indices : [0, 1, 2], + primitiveType: PrimitiveType.TRIANGLE_STRIP + }); + + expect(function() { + GeometryPipeline.computeBinormalAndTangent(geometry); + }).toThrow(); + }); + + it('computeBinormalAndTangent throws when normal is undefined', function() { + var geometry = new Geometry({ + attributes: { + position: new GeometryAttribute({ + values: [0, 0, 0, 1, 0, 0, 0, 1, 0], + componentsPerAttribute: 3, + componentDatatype : ComponentDatatype.FLOAT + + }), + st: new GeometryAttribute({ + values: [0, 0, 1, 1], + componentsPerAttribute: 2, + componentDatatype : ComponentDatatype.FLOAT + }) + }, + indices : [0, 1, 2], + primitiveType: PrimitiveType.TRIANGLE_STRIP + }); + + expect(function() { + GeometryPipeline.computeBinormalAndTangent(geometry); + }).toThrow(); + }); + + it('computeBinormalAndTangent throws when st is undefined', function() { + var geometry = new Geometry({ + attributes: { + position: new GeometryAttribute({ + values: [0, 0, 0, 1, 0, 0, 0, 1, 0], + componentsPerAttribute: 3, + componentDatatype : ComponentDatatype.FLOAT + + }), + normal: new GeometryAttribute({ + values: [0, 0, 0, 1, 0, 0, 0, 1, 0], + componentsPerAttribute: 3, + componentDatatype : ComponentDatatype.FLOAT + + }) + }, + indices : [0, 1, 2], + primitiveType: PrimitiveType.TRIANGLE_STRIP + }); + + expect(function() { + GeometryPipeline.computeBinormalAndTangent(geometry); + }).toThrow(); + }); + + it('computeBinormalAndTangent throws when geometry.indices is undefined', function() { var geometry = new Geometry({ attributes: { position: new GeometryAttribute({ @@ -1150,7 +1309,7 @@ defineSuite([ }), st: new GeometryAttribute({ - values: [0, 1], + values: [0, 0, 1, 1], componentsPerAttribute: 2, componentDatatype : ComponentDatatype.FLOAT }) @@ -1158,13 +1317,42 @@ defineSuite([ primitiveType : PrimitiveType.POINTS }); - geometry = GeometryPipeline.computeBinormalAndTangent(geometry); + expect(function() { + GeometryPipeline.computeBinormalAndTangent(geometry); + }).toThrow(); + }); - expect(typeof geometry.attributes.tangent === 'undefined').toEqual(true); - expect(typeof geometry.attributes.binormal === 'undefined').toEqual(true); + it('computeBinormalAndTangent throws when indices is not a multiple of 3', function() { + var geometry = new Geometry({ + attributes: { + position: new GeometryAttribute({ + values: [0, 0, 0, 1, 0, 0, 0, 1, 0], + componentsPerAttribute: 3, + componentDatatype : ComponentDatatype.FLOAT + + }), + normal: new GeometryAttribute({ + values: [0, 0, 0, 1, 0, 0, 0, 1, 0], + componentsPerAttribute: 3, + componentDatatype : ComponentDatatype.FLOAT + + }), + st: new GeometryAttribute({ + values: [0, 0, 1, 1], + componentsPerAttribute: 2, + componentDatatype : ComponentDatatype.FLOAT + }) + }, + indices : [0, 1, 2, 3, 4], + primitiveType: PrimitiveType.TRIANGLES + }); + + expect(function() { + GeometryPipeline.computeBinormalAndTangent(geometry); + }).toThrow(); }); - it('computeBinormalAndTangent does not compute tangent and binormals when primitive type is not triangle', function() { + it('computeBinormalAndTangent throws when primitive type is not triangle', function() { var geometry = new Geometry({ attributes: { position: new GeometryAttribute({ @@ -1180,7 +1368,7 @@ defineSuite([ }), st: new GeometryAttribute({ - values: [0, 1], + values: [0, 0, 1, 1], componentsPerAttribute: 2, componentDatatype : ComponentDatatype.FLOAT }) @@ -1189,10 +1377,9 @@ defineSuite([ primitiveType: PrimitiveType.TRIANGLE_STRIP }); - geometry = GeometryPipeline.computeBinormalAndTangent(geometry); - - expect(typeof geometry.attributes.tangent === 'undefined').toEqual(true); - expect(typeof geometry.attributes.binormal === 'undefined').toEqual(true); + expect(function() { + GeometryPipeline.computeBinormalAndTangent(geometry); + }).toThrow(); }); it('computeBinormalAndTangent computes tangent and binormal for one triangle', function() { diff --git a/Specs/Scene/PolylineCollectionSpec.js b/Specs/Scene/PolylineCollectionSpec.js index d75b47c5e852..8ac37c3f1f92 100644 --- a/Specs/Scene/PolylineCollectionSpec.js +++ b/Specs/Scene/PolylineCollectionSpec.js @@ -430,7 +430,7 @@ defineSuite([ it('renders 64K vertices of same polyline', function() { var positions = []; - for ( var i = 0; i < (64 * 1024) / 2; ++i) { + for ( var i = 0; i < CesiumMath.SIXTY_FOUR_KILOBYTES / 2; ++i) { positions.push({ x : 0, y : -1, @@ -455,7 +455,7 @@ defineSuite([ it('creates two vertex arrays and renders', function() { var positions = []; - for ( var i = 0; i < (64 * 1024) / 2; ++i) { + for ( var i = 0; i < CesiumMath.SIXTY_FOUR_KILOBYTES / 2; ++i) { positions.push({ x : 0, y : -1, @@ -498,7 +498,7 @@ defineSuite([ it('renders more than 64K vertices of same polyline', function() { var positions = []; - for ( var i = 0; i < 64 * 1024; ++i) { + for ( var i = 0; i < CesiumMath.SIXTY_FOUR_KILOBYTES; ++i) { positions.push({ x : 0, y : -1, @@ -757,7 +757,7 @@ defineSuite([ it('renders more than 64K vertices of different polylines', function() { var positions = []; - for ( var i = 0; i < 64 * 1024; ++i) { + for ( var i = 0; i < CesiumMath.SIXTY_FOUR_KILOBYTES; ++i) { positions.push({ x : -1, y : -1, @@ -797,7 +797,7 @@ defineSuite([ it('renders more than 64K vertices of different polylines of different widths', function() { var positions = []; - for ( var i = 0; i < 64 * 1024 - 2; ++i) { + for ( var i = 0; i < CesiumMath.SIXTY_FOUR_KILOBYTES - 2; ++i) { positions.push({ x : -1, y : -1, From 20ec9b6eb32a5a4d730a3e38ecfb5108cac82561 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Tue, 9 Jul 2013 19:33:30 -0400 Subject: [PATCH 298/306] Update Sandcastle example. --- Apps/Sandcastle/gallery/Geometry and Appearances.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Apps/Sandcastle/gallery/Geometry and Appearances.html b/Apps/Sandcastle/gallery/Geometry and Appearances.html index 0e23d7b12724..52774d993063 100644 --- a/Apps/Sandcastle/gallery/Geometry and Appearances.html +++ b/Apps/Sandcastle/gallery/Geometry and Appearances.html @@ -84,7 +84,7 @@ center : ellipsoid.cartographicToCartesian(Cesium.Cartographic.fromDegrees(-80.0, 35.0)), semiMinorAxis : 200000.0, semiMajorAxis : 500000.0, - bearing : Cesium.Math.toRadians(30.0), + rotation : Cesium.Math.toRadians(30.0), vertexFormat : Cesium.EllipsoidSurfaceAppearance.VERTEX_FORMAT }) }); @@ -151,7 +151,7 @@ }); var ellipsoidGeometry = new Cesium.EllipsoidGeometry({ vertexFormat : Cesium.PerInstanceColorAppearance.VERTEX_FORMAT, - ellipsoid : new Cesium.Ellipsoid(0.5, 0.5, 1.0) + radii : new Cesium.Cartesian3(0.5, 0.5, 1.0) }); instances = []; From fd92e7fcc802b77918627a341afbc32fa7131670 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Tue, 9 Jul 2013 20:11:13 -0400 Subject: [PATCH 299/306] Remove conflicting options from PolygonGeometry. Make PolygonGeometry constructor take a polygon hierarchy and add a new fromPositions function. --- Source/Core/PolygonGeometry.js | 177 ++++++++++++++++----------- Source/Scene/Polygon.js | 38 ++++-- Specs/Core/PolygonGeometrySpec.js | 16 ++- Specs/Scene/GeometryRenderingSpec.js | 4 +- 4 files changed, 144 insertions(+), 91 deletions(-) diff --git a/Source/Core/PolygonGeometry.js b/Source/Core/PolygonGeometry.js index 70439d6d4294..661e34e0f61b 100644 --- a/Source/Core/PolygonGeometry.js +++ b/Source/Core/PolygonGeometry.js @@ -127,28 +127,29 @@ define([ * @alias PolygonGeometry * @constructor * - * @param {Array} [options.positions] An array of positions that defined the corner points of the polygon. - * @param {Object} [options.polygonHierarchy] A polygon hierarchy that can include holes. + * @param {Object} options.polygonHierarchy A polygon hierarchy that can include holes. * @param {Number} [options.height=0.0] The height of the polygon. * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed. * @param {Number} [options.stRotation=0.0] The rotation of the texture coordiantes, in radians. A positive rotation is counter-clockwise. * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid to be used as a reference. * @param {Number} [options.granularity=CesiumMath.RADIANS_PER_DEGREE] The distance, in radians, between each latitude and longitude. Determines the number of positions in the buffer. * + * @exception {DeveloperError} polygonHierarchy is required. * @exception {DeveloperError} At least three positions are required. - * @exception {DeveloperError} positions or polygonHierarchy must be supplied. * @exception {DeveloperError} Duplicate positions result in not enough positions to form a polygon. * * @example * // create a polygon from points * var geometry = new PolygonGeometry({ - * positions : ellipsoid.cartographicArrayToCartesianArray([ - * Cartographic.fromDegrees(-72.0, 40.0), - * Cartographic.fromDegrees(-70.0, 35.0), - * Cartographic.fromDegrees(-75.0, 30.0), - * Cartographic.fromDegrees(-70.0, 30.0), - * Cartographic.fromDegrees(-68.0, 40.0) - * ]) + * polygonHierarchy : { + * positions : ellipsoid.cartographicArrayToCartesianArray([ + * Cartographic.fromDegrees(-72.0, 40.0), + * Cartographic.fromDegrees(-70.0, 35.0), + * Cartographic.fromDegrees(-75.0, 30.0), + * Cartographic.fromDegrees(-70.0, 30.0), + * Cartographic.fromDegrees(-68.0, 40.0) + * ]) + * } * }); * * // create a nested polygon with holes @@ -196,81 +197,65 @@ define([ var stRotation = defaultValue(options.stRotation, 0.0); var height = defaultValue(options.height, 0.0); - var positions = options.positions; var polygonHierarchy = options.polygonHierarchy; + if (typeof polygonHierarchy === 'undefined') { + throw new DeveloperError('options.polygonHierarchy is required.'); + } - var geometries = []; - var geometry; - var boundingSphere; - var i; + // create from a polygon hierarchy + // Algorithm adapted from http://www.geometrictools.com/Documentation/TriangulationByEarClipping.pdf + var polygons = []; + var queue = new Queue(); + queue.enqueue(polygonHierarchy); - var outerPositions; + var i; - if (typeof positions !== 'undefined') { - // create from positions - outerPositions = positions; + while (queue.length !== 0) { + var outerNode = queue.dequeue(); + var outerRing = outerNode.positions; - boundingSphere = BoundingSphere.fromPoints(positions); - geometry = createGeometryFromPositions(ellipsoid, positions, granularity); - if (typeof geometry !== 'undefined') { - geometries.push(geometry); + if (outerRing.length < 3) { + throw new DeveloperError('At least three positions are required.'); } - } else if (typeof polygonHierarchy !== 'undefined') { - // create from a polygon hierarchy - // Algorithm adapted from http://www.geometrictools.com/Documentation/TriangulationByEarClipping.pdf - var polygons = []; - var queue = new Queue(); - queue.enqueue(polygonHierarchy); - - while (queue.length !== 0) { - var outerNode = queue.dequeue(); - var outerRing = outerNode.positions; - - if (outerRing.length < 3) { - throw new DeveloperError('At least three positions are required.'); - } - var numChildren = outerNode.holes ? outerNode.holes.length : 0; - if (numChildren === 0) { - // The outer polygon is a simple polygon with no nested inner polygon. - polygons.push(outerNode.positions); - } else { - // The outer polygon contains inner polygons - var holes = []; - for (i = 0; i < numChildren; i++) { - var hole = outerNode.holes[i]; - holes.push(hole.positions); - - var numGrandchildren = 0; - if (typeof hole.holes !== 'undefined') { - numGrandchildren = hole.holes.length; - } - - for (var j = 0; j < numGrandchildren; j++) { - queue.enqueue(hole.holes[j]); - } + var numChildren = outerNode.holes ? outerNode.holes.length : 0; + if (numChildren === 0) { + // The outer polygon is a simple polygon with no nested inner polygon. + polygons.push(outerNode.positions); + } else { + // The outer polygon contains inner polygons + var holes = []; + for (i = 0; i < numChildren; i++) { + var hole = outerNode.holes[i]; + holes.push(hole.positions); + + var numGrandchildren = 0; + if (typeof hole.holes !== 'undefined') { + numGrandchildren = hole.holes.length; + } + + for (var j = 0; j < numGrandchildren; j++) { + queue.enqueue(hole.holes[j]); } - var combinedPolygon = PolygonPipeline.eliminateHoles(outerRing, holes); - polygons.push(combinedPolygon); } + var combinedPolygon = PolygonPipeline.eliminateHoles(outerRing, holes); + polygons.push(combinedPolygon); } + } - polygonHierarchy = polygons; - - outerPositions = polygonHierarchy[0]; - // The bounding volume is just around the boundary points, so there could be cases for - // contrived polygons on contrived ellipsoids - very oblate ones - where the bounding - // volume doesn't cover the polygon. - boundingSphere = BoundingSphere.fromPoints(outerPositions); + var outerPositions = polygons[0]; + // The bounding volume is just around the boundary points, so there could be cases for + // contrived polygons on contrived ellipsoids - very oblate ones - where the bounding + // volume doesn't cover the polygon. + var boundingSphere = BoundingSphere.fromPoints(outerPositions); - for (i = 0; i < polygonHierarchy.length; i++) { - geometry = createGeometryFromPositions(ellipsoid, polygonHierarchy[i], granularity); - if (typeof geometry !== 'undefined') { - geometries.push(geometry); - } + var geometry; + var geometries = []; + for (var k = 0; k < polygons.length; k++) { + geometry = createGeometryFromPositions(ellipsoid, polygons[k], granularity); + if (typeof geometry !== 'undefined') { + geometries.push(geometry); } - } else { - throw new DeveloperError('positions or hierarchy must be supplied.'); } geometry = GeometryPipeline.combine(geometries); @@ -439,6 +424,54 @@ define([ this.boundingSphere = boundingSphere; }; + /** + * Creates a polygon from an array of positions. + * + * @memberof PolygonGeometry + * + * @param {Array} options.positions An array of positions that defined the corner points of the polygon. + * @param {Number} [options.height=0.0] The height of the polygon. + * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed. + * @param {Number} [options.stRotation=0.0] The rotation of the texture coordiantes, in radians. A positive rotation is counter-clockwise. + * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid to be used as a reference. + * @param {Number} [options.granularity=CesiumMath.RADIANS_PER_DEGREE] The distance, in radians, between each latitude and longitude. Determines the number of positions in the buffer. + * + * @exception {DeveloperError} options.positions is required. + * @exception {DeveloperError} At least three positions are required. + * @exception {DeveloperError} Duplicate positions result in not enough positions to form a polygon. + * + * @example + * // create a polygon from points + * var geometry = new PolygonGeometry({ + * positions : ellipsoid.cartographicArrayToCartesianArray([ + * Cartographic.fromDegrees(-72.0, 40.0), + * Cartographic.fromDegrees(-70.0, 35.0), + * Cartographic.fromDegrees(-75.0, 30.0), + * Cartographic.fromDegrees(-70.0, 30.0), + * Cartographic.fromDegrees(-68.0, 40.0) + * ]) + * }); + */ + PolygonGeometry.fromPositions = function(options) { + options = defaultValue(options, defaultValue.EMPTY_OBJECT); + + if (typeof options.positions === 'undefined') { + throw new DeveloperError('options.positions is required.'); + } + + var newOptions = { + polygonHierarchy : { + positions : options.positions + }, + height : options.height, + vertexFormat : options.vertexFormat, + stRotation : options.stRotation, + ellipsoid : options.ellipsoid, + granularity : options.granularity + }; + return new PolygonGeometry(newOptions); + }; + return PolygonGeometry; }); diff --git a/Source/Scene/Polygon.js b/Source/Scene/Polygon.js index b6949651cc22..f0da0fa4e74c 100644 --- a/Source/Scene/Polygon.js +++ b/Source/Scene/Polygon.js @@ -276,18 +276,32 @@ define([ return; } - var instance = new GeometryInstance({ - geometry : new PolygonGeometry({ - positions : this._positions, - polygonHierarchy : this._polygonHierarchy, - height : this.height, - vertexFormat : EllipsoidSurfaceAppearance.VERTEX_FORMAT, - stRotation : this.textureRotationAngle, - ellipsoid : this.ellipsoid, - granularity : this.granularity - }), - id : this - }); + var instance; + if (typeof this._positions !== 'undefined') { + instance = new GeometryInstance({ + geometry : PolygonGeometry.fromPositions({ + positions : this._positions, + height : this.height, + vertexFormat : EllipsoidSurfaceAppearance.VERTEX_FORMAT, + stRotation : this.textureRotationAngle, + ellipsoid : this.ellipsoid, + granularity : this.granularity + }), + id : this + }); + } else { + instance = new GeometryInstance({ + geometry : new PolygonGeometry({ + polygonHierarchy : this._polygonHierarchy, + height : this.height, + vertexFormat : EllipsoidSurfaceAppearance.VERTEX_FORMAT, + stRotation : this.textureRotationAngle, + ellipsoid : this.ellipsoid, + granularity : this.granularity + }), + id : this + }); + } this._primitive = new Primitive({ geometryInstances : instance, diff --git a/Specs/Core/PolygonGeometrySpec.js b/Specs/Core/PolygonGeometrySpec.js index 96468a521468..1700875bf85d 100644 --- a/Specs/Core/PolygonGeometrySpec.js +++ b/Specs/Core/PolygonGeometrySpec.js @@ -16,15 +16,21 @@ defineSuite([ "use strict"; /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/ - it('throws without positions or hierarchy', function() { + it('throws without hierarchy', function() { expect(function() { return new PolygonGeometry(); }).toThrow(); }); + it('throws without positions', function() { + expect(function() { + return PolygonGeometry.fromPositions(); + }).toThrow(); + }); + it('throws with less than three positions', function() { expect(function() { - return new PolygonGeometry({ positions : [new Cartesian3()] }); + return PolygonGeometry.fromPositions({ positions : [new Cartesian3()] }); }).toThrow(); }); @@ -44,7 +50,7 @@ defineSuite([ var ellipsoid = Ellipsoid.UNIT_SPHERE; expect(function() { - return new PolygonGeometry({ + return PolygonGeometry.fromPositions({ positions : [ ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(0.0, 0.0, 0.0)), ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(0.0, 0.0, 0.0)), @@ -81,7 +87,7 @@ defineSuite([ }); it('computes positions', function() { - var p = new PolygonGeometry({ + var p = PolygonGeometry.fromPositions({ vertexformat : VertexFormat.POSITION_ONLY, positions : Ellipsoid.WGS84.cartographicArrayToCartesianArray([ Cartographic.fromDegrees(-50.0, -50.0, 0.0), @@ -97,7 +103,7 @@ defineSuite([ }); it('computes all attributes', function() { - var p = new PolygonGeometry({ + var p = PolygonGeometry.fromPositions({ vertexFormat : VertexFormat.ALL, positions : Ellipsoid.WGS84.cartographicArrayToCartesianArray([ Cartographic.fromDegrees(-50.0, -50.0, 0.0), diff --git a/Specs/Scene/GeometryRenderingSpec.js b/Specs/Scene/GeometryRenderingSpec.js index 1708187048da..8e55ddfe7610 100644 --- a/Specs/Scene/GeometryRenderingSpec.js +++ b/Specs/Scene/GeometryRenderingSpec.js @@ -510,7 +510,7 @@ defineSuite([ var instance; beforeAll(function() { instance = new GeometryInstance({ - geometry : new PolygonGeometry({ + geometry : PolygonGeometry.fromPositions({ vertexFormat : PerInstanceColorAppearance.FLAT_VERTEX_FORMAT, ellipsoid : ellipsoid, positions : ellipsoid.cartographicArrayToCartesianArray([ @@ -545,7 +545,7 @@ defineSuite([ it('at height', function() { var atHeight = new GeometryInstance({ - geometry : new PolygonGeometry({ + geometry : PolygonGeometry.fromPositions({ vertexFormat : PerInstanceColorAppearance.FLAT_VERTEX_FORMAT, ellipsoid : ellipsoid, positions : ellipsoid.cartographicArrayToCartesianArray([ From 2ae97f802b855931ef6e74fe3b9a24ea2d5aa00e Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Wed, 10 Jul 2013 13:08:35 -0400 Subject: [PATCH 300/306] Update pointInsideTriangle doc and more updates based on review. --- CHANGES.md | 1 + Source/Core/PolylinePipeline.js | 2 +- Source/Core/pointInsideTriangle.js | 10 +++++----- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 37d618d72b79..8ad5624c1552 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -24,6 +24,7 @@ Beta Releases * Removed `PolygonPipeline.wrapLongitude`. Use `GeometryPipeline.wrapLongitude` instead. * Added `surfaceHeight` parameter to `BoundingSphere.fromExtent3D`. * Added `surfaceHeight` parameter to `Extent.subsample`. + * Renamed `pointInsideTriangle2D` to `pointInsideTriangle`. * Added `ExtentPrimitive`. * Added Geometry and Appearances [#911](https://github.com/AnalyticalGraphicsInc/cesium/pull/911). * Added `PolylinePipeline.removeDuplicates`. diff --git a/Source/Core/PolylinePipeline.js b/Source/Core/PolylinePipeline.js index 147a6414f1a8..dcf90f21ad6a 100644 --- a/Source/Core/PolylinePipeline.js +++ b/Source/Core/PolylinePipeline.js @@ -150,7 +150,7 @@ define([ var v0 = positions[i - 1]; var v1 = positions[i]; - if (!v0.equals(v1)) { + if (!Cartesian3.equals(v0, v1)) { cleanedPositions.push(v1); // Shallow copy! } } diff --git a/Source/Core/pointInsideTriangle.js b/Source/Core/pointInsideTriangle.js index e277a1150015..9f2cfcca3d6b 100644 --- a/Source/Core/pointInsideTriangle.js +++ b/Source/Core/pointInsideTriangle.js @@ -12,14 +12,14 @@ define([ var coords = new Cartesian3(); /** - * Determines if a 2D point is inside a triangle. + * Determines if a point is inside a triangle. * * @exports pointInsideTriangle * - * @param {Cartesian2} point The point to test. - * @param {Cartesian2} p0 The first point of the triangle. - * @param {Cartesian2} p1 The second point of the triangle. - * @param {Cartesian2} p2 The third point of the triangle. + * @param {Cartesian2|Cartesian3} point The point to test. + * @param {Cartesian2|Cartesian3} p0 The first point of the triangle. + * @param {Cartesian2|Cartesian3} p1 The second point of the triangle. + * @param {Cartesian2|Cartesian3} p2 The third point of the triangle. * * @return {Boolean} true if the point is inside the triangle; otherwise, false. * From 950a6bdcae0cadf667da4a1b633f0cf35f84fc51 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Wed, 10 Jul 2013 13:22:24 -0400 Subject: [PATCH 301/306] Fix texture coordinates for ellipses/circles. --- Source/Core/EllipseGeometry.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Source/Core/EllipseGeometry.js b/Source/Core/EllipseGeometry.js index af314120e99c..153ae6b9df45 100644 --- a/Source/Core/EllipseGeometry.js +++ b/Source/Core/EllipseGeometry.js @@ -3,10 +3,12 @@ define([ './defaultValue', './BoundingSphere', './Cartesian3', + './Cartographic', './ComponentDatatype', './IndexDatatype', './DeveloperError', './Ellipsoid', + './GeographicProjection', './GeometryAttribute', './GeometryAttributes', './Math', @@ -18,10 +20,12 @@ define([ defaultValue, BoundingSphere, Cartesian3, + Cartographic, ComponentDatatype, IndexDatatype, DeveloperError, Ellipsoid, + GeographicProjection, GeometryAttribute, GeometryAttributes, CesiumMath, @@ -69,6 +73,8 @@ define([ var unitPosScratch = new Cartesian3(); var eastVecScratch = new Cartesian3(); var northVecScratch = new Cartesian3(); + var scratchCartographic = new Cartographic(); + var projectedCenterScratch = new Cartesian3(); /** * A {@link Geometry} that represents vertices and indices for an ellipse on the ellipsoid. @@ -262,12 +268,16 @@ define([ var tangent; var binormal; + var projection = new GeographicProjection(ellipsoid); + var projectedCenter = projection.project(ellipsoid.cartesianToCartographic(center, scratchCartographic), projectedCenterScratch); + var length = positions.length; for (i = 0; i < length; i += 3) { position = Cartesian3.fromArray(positions, i, scratchCartesian2); if (vertexFormat.st) { - var relativeToCenter = Cartesian3.subtract(position, center); + var projectedPoint = projection.project(ellipsoid.cartesianToCartographic(position, scratchCartographic), scratchCartesian3); + var relativeToCenter = Cartesian3.subtract(projectedPoint, projectedCenter, projectedPoint); textureCoordinates[textureCoordIndex++] = (relativeToCenter.x + semiMajorAxis) / (2.0 * semiMajorAxis); textureCoordinates[textureCoordIndex++] = (relativeToCenter.y + semiMinorAxis) / (2.0 * semiMinorAxis); } From fa661fe9d8dc3a4a6e8613945a9de0af11918109 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Wed, 10 Jul 2013 18:57:45 -0400 Subject: [PATCH 302/306] More updates based on review. --- Source/Core/PolylinePipeline.js | 2 +- Source/Core/WallGeometry.js | 318 +++++++++++++++++--------- Source/Core/barycentricCoordinates.js | 18 +- Source/Scene/ExtentPrimitive.js | 2 +- Specs/Core/WallGeometrySpec.js | 91 +++++++- 5 files changed, 305 insertions(+), 126 deletions(-) diff --git a/Source/Core/PolylinePipeline.js b/Source/Core/PolylinePipeline.js index dcf90f21ad6a..147a6414f1a8 100644 --- a/Source/Core/PolylinePipeline.js +++ b/Source/Core/PolylinePipeline.js @@ -150,7 +150,7 @@ define([ var v0 = positions[i - 1]; var v1 = positions[i]; - if (!Cartesian3.equals(v0, v1)) { + if (!v0.equals(v1)) { cleanedPositions.push(v1); // Shallow copy! } } diff --git a/Source/Core/WallGeometry.js b/Source/Core/WallGeometry.js index 51611e64b60b..aa6d0b65907c 100644 --- a/Source/Core/WallGeometry.js +++ b/Source/Core/WallGeometry.js @@ -37,6 +37,37 @@ define([ WindingOrder) { "use strict"; + function removeDuplicates(positions, topHeights, bottomHeights, cleanedPositions, cleanedTopHeights, cleanedBottomHeights) { + var length = positions.length; + + cleanedPositions.push(positions[0]); + + if (typeof topHeights !== 'undefined') { + cleanedTopHeights.push(topHeights[0]); + } + + if (typeof bottomHeights !== 'undefined') { + cleanedBottomHeights.push(bottomHeights[0]); + } + + for (var i = 1; i < length; ++i) { + var v0 = positions[i - 1]; + var v1 = positions[i]; + + if (!Cartesian3.equals(v0, v1)) { + cleanedPositions.push(v1); // Shallow copy! + + if (typeof topHeights !== 'undefined') { + cleanedTopHeights.push(topHeights[i]); + } + + if (typeof bottomHeights !== 'undefined') { + cleanedBottomHeights.push(bottomHeights[i]); + } + } + } + } + var scratchCartographic = new Cartographic(); var scratchCartesian3Position1 = new Cartesian3(); var scratchCartesian3Position2 = new Cartesian3(); @@ -48,22 +79,21 @@ define([ /** * A {@link Geometry} that represents a wall, which is similar to a KML line string. A wall is defined by a series of points, * which extrude down to the ground. Optionally, they can extrude downwards to a specified height. - * The points in the wall can be offset by supplied terrain elevation data. * * @alias WallGeometry * @constructor * * @param {Array} positions An array of Cartesian objects, which are the points of the wall. - * @param {Array} [terrain] Has to denote the same points as in positions, with the ground elevation reflecting the terrain elevation. - * @param {Number} [top] The top of the wall. If specified, the top of the wall is treated as this - * height, and the information in the positions array is disregarded. - * @param {Number} [bottom] The bottom of the wall. If specified, the bottom of the wall is treated as - * this height. Otherwise, its treated as 'ground' (the WGS84 ellipsoid height 0). + * @param {Array} [maximumHeights] An array parallel to positions that give the maximum height of the + * wall at positions. If undefined, the height of each position in used. + * @param {Array} [minimumHeights] An array parallel to positions that give the minimum height of the + * wall at positions. If undefined, the height at each position is 0.0. * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid for coordinate manipulation * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed. * * @exception {DeveloperError} positions is required. - * @exception {DeveloperError} positions and terrain points must have the same length. + * @exception {DeveloperError} positions and maximumHeights must have the same length. + * @exception {DeveloperError} positions and minimumHeights must have the same length. * * @example * var positions = [ @@ -83,9 +113,8 @@ define([ options = defaultValue(options, defaultValue.EMPTY_OBJECT); var wallPositions = options.positions; - var terrain = options.terrain; - var top = options.top; - var bottom = defaultValue(options.bottom, 0); + var maximumHeights = options.maximumHeights; + var minimumHeights = options.minimumHeights; var ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84); var vertexFormat = defaultValue(options.vertexFormat, VertexFormat.DEFAULT); @@ -93,11 +122,23 @@ define([ throw new DeveloperError('positions is required.'); } - if (typeof terrain !== 'undefined' && terrain.length !== wallPositions.length) { - throw new DeveloperError('positions and terrain points must have the same length.'); + if (typeof maximumHeights !== 'undefined' && maximumHeights.length !== wallPositions.length) { + throw new DeveloperError('positions and maximumHeights must have the same length.'); + } + + if (typeof minimumHeights !== 'undefined' && minimumHeights.length !== wallPositions.length) { + throw new DeveloperError('positions and minimumHeights must have the same length.'); } - wallPositions = PolylinePipeline.removeDuplicates(wallPositions); + var cleanedPositions = []; + var cleanedMaximumHeights = (typeof maximumHeights !== 'undefined') ? [] : undefined; + var cleanedMinimumHeights = (typeof minimumHeights !== 'undefined') ? [] : undefined; + removeDuplicates(wallPositions, maximumHeights, minimumHeights, cleanedPositions, cleanedMaximumHeights, cleanedMinimumHeights); + + wallPositions = cleanedPositions; + maximumHeights = cleanedMaximumHeights; + minimumHeights = cleanedMinimumHeights; + if (wallPositions.length >= 3) { // Order positions counter-clockwise var tangentPlane = EllipsoidTangentPlane.fromPoints(wallPositions, ellipsoid); @@ -105,19 +146,20 @@ define([ if (PolygonPipeline.computeWindingOrder2D(positions2D) === WindingOrder.CLOCKWISE) { wallPositions.reverse(); + + if (typeof maximumHeights !== 'undefined') { + maximumHeights.reverse(); + } + + if (typeof minimumHeights !== 'undefined') { + minimumHeights.reverse(); + } } } + var i; - var flatPositions = []; var length = wallPositions.length; - for (i = 0; i < length - 1; i++) { - var p1 = wallPositions[i]; - var p2 = wallPositions[i+1]; - flatPositions.push(p1.x, p1.y, p1.z); - flatPositions.push(p2.x, p2.y, p2.z); - } - - var size = flatPositions.length * 2; + var size = 2 * (length - 1) * 2 * 3; var positions = vertexFormat.position ? new Float64Array(size) : undefined; var normals = vertexFormat.normal ? new Float32Array(size) : undefined; @@ -133,111 +175,106 @@ define([ // add lower and upper points one after the other, lower // points being even and upper points being odd - length = flatPositions.length; var normal = scratchNormal; var tangent = scratchTangent; var binormal = scratchBinormal; var recomputeNormal = true; - for (i = 0; i < length; i += 3) { - var pos = Cartesian3.fromArray(flatPositions, i, scratchCartesian3Position1); - var c = ellipsoid.cartesianToCartographic(pos, scratchCartographic); - var origHeight = c.height; - c.height = 0.0; - - var terrainHeight = 0.0; - if (terrain !== undefined) { - var h = terrain[i/3].height; - if (!isNaN(h)) { - terrainHeight = h; - } - } + for (i = 0; i < length - 1; ++i) { + for (var j = 0; j < 2; ++j) { + var index = i + j; - c.height = bottom + terrainHeight; - var bottomPosition = ellipsoid.cartographicToCartesian(c, scratchCartesian3Position1); + var pos = wallPositions[index]; + var c = ellipsoid.cartesianToCartographic(pos, scratchCartographic); - // get the original height back, or set the top value - if (typeof top !== 'undefined') { - c.height = top + terrain.height; - } else { - c.height = origHeight + terrainHeight; - } + if (typeof maximumHeights !== 'undefined') { + c.height = maximumHeights[index]; + } + var topPosition = ellipsoid.cartographicToCartesian(c, scratchCartesian3Position1); - var topPosition = ellipsoid.cartographicToCartesian(c, scratchCartesian3Position2); + c.height = 0.0; + if (typeof minimumHeights !== 'undefined') { + c.height += minimumHeights[index]; + } else { + c.height = 0.0; + } - if (vertexFormat.position) { - // insert the lower point - positions[positionIndex++] = bottomPosition.x; - positions[positionIndex++] = bottomPosition.y; - positions[positionIndex++] = bottomPosition.z; + var bottomPosition = ellipsoid.cartographicToCartesian(c, scratchCartesian3Position2); - // insert the upper point - positions[positionIndex++] = topPosition.x; - positions[positionIndex++] = topPosition.y; - positions[positionIndex++] = topPosition.z; - } + if (vertexFormat.position) { + // insert the lower point + positions[positionIndex++] = bottomPosition.x; + positions[positionIndex++] = bottomPosition.y; + positions[positionIndex++] = bottomPosition.z; - if (vertexFormat.normal || vertexFormat.tangent || vertexFormat.binormal) { - var nextPosition; - if (i+3 < length) { - nextPosition = Cartesian3.fromArray(flatPositions, i+3, scratchCartesian3Position3); + // insert the upper point + positions[positionIndex++] = topPosition.x; + positions[positionIndex++] = topPosition.y; + positions[positionIndex++] = topPosition.z; } - if (recomputeNormal) { - nextPosition = nextPosition.subtract(topPosition, nextPosition); - bottomPosition = bottomPosition.subtract(topPosition, bottomPosition); - normal = Cartesian3.cross(bottomPosition, nextPosition, normal).normalize(normal); - if (vertexFormat.tangent) { - tangent = nextPosition.normalize(tangent); + if (vertexFormat.normal || vertexFormat.tangent || vertexFormat.binormal) { + var nextPosition; + if (index + 1 < length) { + nextPosition = Cartesian3.clone(wallPositions[index + 1], scratchCartesian3Position3); } - if (vertexFormat.binormal) { - binormal = Cartesian3.cross(normal, tangent, binormal).normalize(binormal); + + if (recomputeNormal) { + nextPosition = nextPosition.subtract(topPosition, nextPosition); + bottomPosition = bottomPosition.subtract(topPosition, bottomPosition); + normal = Cartesian3.cross(bottomPosition, nextPosition, normal).normalize(normal); + if (vertexFormat.tangent) { + tangent = nextPosition.normalize(tangent); + } + if (vertexFormat.binormal) { + binormal = Cartesian3.cross(normal, tangent, binormal).normalize(binormal); + } + recomputeNormal = false; } - recomputeNormal = false; - } - if (topPosition.equalsEpsilon(nextPosition, CesiumMath.EPSILON4)) { // if we've reached a corner - recomputeNormal = true; - } + if (j === 1) { + recomputeNormal = true; + } - if (vertexFormat.normal) { - normals[normalIndex++] = normal.x; - normals[normalIndex++] = normal.y; - normals[normalIndex++] = normal.z; + if (vertexFormat.normal) { + normals[normalIndex++] = normal.x; + normals[normalIndex++] = normal.y; + normals[normalIndex++] = normal.z; - normals[normalIndex++] = normal.x; - normals[normalIndex++] = normal.y; - normals[normalIndex++] = normal.z; - } + normals[normalIndex++] = normal.x; + normals[normalIndex++] = normal.y; + normals[normalIndex++] = normal.z; + } - if (vertexFormat.tangent) { - tangents[tangentIndex++] = tangent.x; - tangents[tangentIndex++] = tangent.y; - tangents[tangentIndex++] = tangent.z; + if (vertexFormat.tangent) { + tangents[tangentIndex++] = tangent.x; + tangents[tangentIndex++] = tangent.y; + tangents[tangentIndex++] = tangent.z; - tangents[tangentIndex++] = tangent.x; - tangents[tangentIndex++] = tangent.y; - tangents[tangentIndex++] = tangent.z; - } + tangents[tangentIndex++] = tangent.x; + tangents[tangentIndex++] = tangent.y; + tangents[tangentIndex++] = tangent.z; + } - if (vertexFormat.binormal) { - binormals[binormalIndex++] = binormal.x; - binormals[binormalIndex++] = binormal.y; - binormals[binormalIndex++] = binormal.z; + if (vertexFormat.binormal) { + binormals[binormalIndex++] = binormal.x; + binormals[binormalIndex++] = binormal.y; + binormals[binormalIndex++] = binormal.z; - binormals[binormalIndex++] = binormal.x; - binormals[binormalIndex++] = binormal.y; - binormals[binormalIndex++] = binormal.z; + binormals[binormalIndex++] = binormal.x; + binormals[binormalIndex++] = binormal.y; + binormals[binormalIndex++] = binormal.z; + } } - } - if (vertexFormat.st) { - var s = i / (length - 1); + if (vertexFormat.st) { + var s = index / (length - 1); - textureCoordinates[textureCoordIndex++] = s; - textureCoordinates[textureCoordIndex++] = 0.0; + textureCoordinates[textureCoordIndex++] = s; + textureCoordinates[textureCoordIndex++] = 0.0; - textureCoordinates[textureCoordIndex++] = s; - textureCoordinates[textureCoordIndex++] = 1.0; + textureCoordinates[textureCoordIndex++] = s; + textureCoordinates[textureCoordIndex++] = 1.0; + } } } @@ -298,7 +335,7 @@ define([ // C (i) D (i+2) F // - var numVertices = size/3; + var numVertices = size / 3; size -= 6; var indices = IndexDatatype.createTypedArray(numVertices, size); @@ -306,8 +343,8 @@ define([ for (i = 0; i < numVertices - 2; i += 2) { var LL = i; var LR = i + 2; - var pl = Cartesian3.fromArray(positions, LL*3, scratchCartesian3Position1); - var pr = Cartesian3.fromArray(positions, LR*3, scratchCartesian3Position2); + var pl = Cartesian3.fromArray(positions, LL * 3, scratchCartesian3Position1); + var pr = Cartesian3.fromArray(positions, LR * 3, scratchCartesian3Position2); if (Cartesian3.equalsEpsilon(pl, pr, CesiumMath.EPSILON6)) { continue; } @@ -354,6 +391,77 @@ define([ this.boundingSphere = new BoundingSphere.fromVertices(positions); }; + /** + * A {@link Geometry} that represents a wall, which is similar to a KML line string. A wall is defined by a series of points, + * which extrude down to the ground. Optionally, they can extrude downwards to a specified height. + * + * @memberof WallGeometry + * + * @param {Array} positions An array of Cartesian objects, which are the points of the wall. + * @param {Number} [maximumHeight] A constant that defines the maximum height of the + * wall at positions. If undefined, the height of each position in used. + * @param {Number} [minimumHeight] A constant that defines the minimum height of the + * wall at positions. If undefined, the height at each position is 0.0. + * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid for coordinate manipulation + * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed. + * + * @exception {DeveloperError} positions is required. + * + * @example + * var positions = [ + * Cartographic.fromDegrees(19.0, 47.0, 10000.0), + * Cartographic.fromDegrees(19.0, 48.0, 10000.0), + * Cartographic.fromDegrees(20.0, 48.0, 10000.0), + * Cartographic.fromDegrees(20.0, 47.0, 10000.0), + * Cartographic.fromDegrees(19.0, 47.0, 10000.0) + * ]; + * + * // create a wall that spans from 10000 meters to 20000 meters + * var wall = new WallGeometry({ + * positions : ellipsoid.cartographicArrayToCartesianArray(positions), + * topHeight : 20000.0, + * bottomHeight : 10000.0 + * }); + */ + WallGeometry.fromConstantHeights = function(options) { + options = defaultValue(options, defaultValue.EMPTY_OBJECT); + + var positions = options.positions; + if (typeof positions === 'undefined') { + throw new DeveloperError('options.positions is required.'); + } + + var minHeights; + var maxHeights; + + var min = options.minimumHeight; + var max = options.maximumHeight; + if (typeof min !== 'undefined' || typeof max !== 'undefined') { + var length = positions.length; + minHeights = (typeof min !== 'undefined') ? new Array(length) : undefined; + maxHeights = (typeof max !== 'undefined') ? new Array(length) : undefined; + + for (var i = 0; i < length; ++i) { + if (typeof min !== 'undefined') { + minHeights[i] = min; + } + + if (typeof max !== 'undefined') { + maxHeights[i] = max; + } + } + } + + var newOptions = { + positions : positions, + maximumHeights : maxHeights, + minimumHeights : minHeights, + ellipsoid : options.ellipsoid, + vertexFormat : options.vertexFormat + }; + return new WallGeometry(newOptions); + }; + return WallGeometry; }); diff --git a/Source/Core/barycentricCoordinates.js b/Source/Core/barycentricCoordinates.js index 472f87959db4..f01baa85e342 100644 --- a/Source/Core/barycentricCoordinates.js +++ b/Source/Core/barycentricCoordinates.js @@ -7,15 +7,19 @@ define([ DeveloperError) { "use strict"; + var scratchCartesian1 = new Cartesian3(); + var scratchCartesian2 = new Cartesian3(); + var scratchCartesian3 = new Cartesian3(); + /** * Computes the barycentric coordinates for a point with respect to a triangle. * * @exports pointInsideTriangle * - * @param {Cartesian3} point The point to test. - * @param {Cartesian3} p0 The first point of the triangle, corresponding to the barycentric x-axis. - * @param {Cartesian3} p1 The second point of the triangle, corresponding to the barycentric y-axis. - * @param {Cartesian3} p2 The third point of the triangle, corresponding to the barycentric z-axis. + * @param {Cartesian2|Cartesian3} point The point to test. + * @param {Cartesian2|Cartesian3} p0 The first point of the triangle, corresponding to the barycentric x-axis. + * @param {Cartesian2|Cartesian3} p1 The second point of the triangle, corresponding to the barycentric y-axis. + * @param {Cartesian2|Cartesian3} p2 The third point of the triangle, corresponding to the barycentric z-axis. * @param {Cartesian3} [result] The object onto which to store the result. * * @return {Cartesian3} The modified result parameter or a new Cartesian3 instance if one was not provided. @@ -40,9 +44,9 @@ define([ } // Implementation based on http://www.blackpawn.com/texts/pointinpoly/default.html. - var v0 = p1.subtract(p0); - var v1 = p2.subtract(p0); - var v2 = point.subtract(p0); + var v0 = p1.subtract(p0, scratchCartesian1); + var v1 = p2.subtract(p0, scratchCartesian2); + var v2 = point.subtract(p0, scratchCartesian3); var dot00 = v0.dot(v0); var dot01 = v0.dot(v1); diff --git a/Source/Scene/ExtentPrimitive.js b/Source/Scene/ExtentPrimitive.js index 6a49e3abbb88..ce1032c3132a 100644 --- a/Source/Scene/ExtentPrimitive.js +++ b/Source/Scene/ExtentPrimitive.js @@ -222,7 +222,7 @@ define([ * isDestroyed will result in a {@link DeveloperError} exception. Therefore, * assign the return value (undefined) to the object as done in the example. * - * @memberof Polygon + * @memberof Extent * * @return {undefined} * diff --git a/Specs/Core/WallGeometrySpec.js b/Specs/Core/WallGeometrySpec.js index 36841f7cd15c..08b8e16788af 100644 --- a/Specs/Core/WallGeometrySpec.js +++ b/Specs/Core/WallGeometrySpec.js @@ -1,13 +1,17 @@ /*global defineSuite*/ defineSuite([ 'Core/WallGeometry', + 'Core/Cartesian3', 'Core/Cartographic', 'Core/Ellipsoid', + 'Core/Math', 'Core/VertexFormat' ], function( WallGeometry, + Cartesian3, Cartographic, Ellipsoid, + CesiumMath, VertexFormat) { "use strict"; /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/ @@ -15,17 +19,25 @@ defineSuite([ var ellipsoid = Ellipsoid.WGS84; it('throws with no positions', function() { + expect(function() { + return new WallGeometry(); + }).toThrow(); + }); + + it('throws when positions and minimumHeights length do not match', function() { expect(function() { return new WallGeometry({ + positions : new Array(2), + minimumHeights : new Array(3) }); }).toThrow(); }); - it('throws when length of positions and terrain points are not equal', function() { + it('throws when positions and maximumHeights length do not match', function() { expect(function() { return new WallGeometry({ - positions : new Array(3), - terrain : new Array(2) + positions : new Array(2), + maximumHeights : new Array(3) }); }).toThrow(); }); @@ -41,29 +53,45 @@ defineSuite([ positions : ellipsoid.cartographicArrayToCartesianArray(coords) }); - expect(w.attributes.position.values.length).toEqual(2 * 2 * 3); + var positions = w.attributes.position.values; + expect(positions.length).toEqual(2 * 2 * 3); expect(w.indices.length).toEqual(2 * 3); + + var cartographic = ellipsoid.cartesianToCartographic(Cartesian3.fromArray(positions, 0)); + expect(cartographic.height).toEqualEpsilon(0.0, CesiumMath.EPSILON9); + + cartographic = ellipsoid.cartesianToCartographic(Cartesian3.fromArray(positions, 3)); + expect(cartographic.height).toEqualEpsilon(1000.0, CesiumMath.EPSILON9); }); - it('creates positions relative to terrain', function() { + it('creates positions with minimum and maximum heights', function() { var coords = [ Cartographic.fromDegrees(49.0, 18.0, 1000.0), Cartographic.fromDegrees(50.0, 18.0, 1000.0) ]; - var terrain = [ - Cartographic.fromDegrees(49.0, 18.0, 100.0), - Cartographic.fromDegrees(50.0, 18.0, 110.0) - ]; - var w = new WallGeometry({ vertexFormat : VertexFormat.POSITION_ONLY, positions : ellipsoid.cartographicArrayToCartesianArray(coords), - terrain : terrain + minimumHeights : [1000.0, 2000.0], + maximumHeights : [3000.0, 4000.0] }); - expect(w.attributes.position.values.length).toEqual(2 * 2 * 3); + var positions = w.attributes.position.values; + expect(positions.length).toEqual(2 * 2 * 3); expect(w.indices.length).toEqual(2 * 3); + + var cartographic = ellipsoid.cartesianToCartographic(Cartesian3.fromArray(positions, 0)); + expect(cartographic.height).toEqualEpsilon(1000.0, CesiumMath.EPSILON8); + + cartographic = ellipsoid.cartesianToCartographic(Cartesian3.fromArray(positions, 3)); + expect(cartographic.height).toEqualEpsilon(3000.0, CesiumMath.EPSILON8); + + cartographic = ellipsoid.cartesianToCartographic(Cartesian3.fromArray(positions, 6)); + expect(cartographic.height).toEqualEpsilon(2000.0, CesiumMath.EPSILON8); + + cartographic = ellipsoid.cartesianToCartographic(Cartesian3.fromArray(positions, 9)); + expect(cartographic.height).toEqualEpsilon(4000.0, CesiumMath.EPSILON8); }); it('creates all attributes', function() { @@ -85,5 +113,44 @@ defineSuite([ expect(w.attributes.st.values.length).toEqual(4 * 2 * 2); expect(w.indices.length).toEqual((4 * 2 - 2) * 3); }); + + it('fromConstantHeights throws without positions', function() { + expect(function() { + return WallGeometry.fromConstantHeights(); + }).toThrow(); + }); + + it('creates positions with constant minimum and maximum heights', function() { + var coords = [ + Cartographic.fromDegrees(49.0, 18.0, 1000.0), + Cartographic.fromDegrees(50.0, 18.0, 1000.0) + ]; + + var min = 1000.0; + var max = 2000.0; + + var w = WallGeometry.fromConstantHeights({ + vertexFormat : VertexFormat.POSITION_ONLY, + positions : ellipsoid.cartographicArrayToCartesianArray(coords), + minimumHeight : min, + maximumHeight : max + }); + + var positions = w.attributes.position.values; + expect(positions.length).toEqual(2 * 2 * 3); + expect(w.indices.length).toEqual(2 * 3); + + var cartographic = ellipsoid.cartesianToCartographic(Cartesian3.fromArray(positions, 0)); + expect(cartographic.height).toEqualEpsilon(min, CesiumMath.EPSILON8); + + cartographic = ellipsoid.cartesianToCartographic(Cartesian3.fromArray(positions, 3)); + expect(cartographic.height).toEqualEpsilon(max, CesiumMath.EPSILON8); + + cartographic = ellipsoid.cartesianToCartographic(Cartesian3.fromArray(positions, 6)); + expect(cartographic.height).toEqualEpsilon(min, CesiumMath.EPSILON8); + + cartographic = ellipsoid.cartesianToCartographic(Cartesian3.fromArray(positions, 9)); + expect(cartographic.height).toEqualEpsilon(max, CesiumMath.EPSILON8); + }); }); From 3d8fe82a14ff6f5f691eadcecc9ef92771aeb704 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Wed, 10 Jul 2013 19:29:53 -0400 Subject: [PATCH 303/306] More changes based on review. --- Source/Scene/Primitive.js | 35 +++++++-------- .../Scene/createTangentSpaceDebugPrimitive.js | 17 ++++--- .../BaseLayerPicker/BaseLayerPicker.js | 32 +------------- .../BaseLayerPickerViewModel.js | 6 +-- Specs/Scene/PrimitiveSpec.js | 44 +++++++++---------- 5 files changed, 52 insertions(+), 82 deletions(-) diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index e9d2092ec5dd..759e4d4aacbf 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -49,16 +49,16 @@ define([ /** * A primitive represents geometry in the {@link Scene}. The geometry can be from a single {@link GeometryInstance} - * as shown in Code Example 1 below, or from an array of instances, even if the geometry is from different + * as shown in example 1 below, or from an array of instances, even if the geometry is from different * geometry types, e.g., an {@link ExtentGeometry} and an {@link EllipsoidGeometry} as shown in Code Example 2. *

    * A primitive combines geometry instances with an {@link Appearance} that describes the full shading, including - * {@link Material} and {@link Renderstate}. Roughly, the geometry instance defines the structure and placement, + * {@link Material} and {@link RenderState}. Roughly, the geometry instance defines the structure and placement, * and the appearance defines the visual characteristics. Decoupling geometry and appearance allows us to mix - * and max most of them, and to easily add new geometry types and appearances. + * and match most of them and add a new geometry or appearance independently of each other. *

    *

    - * Combing multiple instances in one primitive is called batching, and significantly improves performance for static data. + * Combining multiple instances into one primitive is called batching, and significantly improves performance for static data. * Instances can be individually picked; {@link Context#pick} returns their {@link GeometryInstance#id}. Using * per-instance appearances like {@link PerInstanceColorAppearance}, each instance can also have a unique color. *

    @@ -68,9 +68,9 @@ define([ * * @param {Array} [options.geometryInstances=undefined] The geometry instances - or a single geometry instance - to render. * @param {Appearance} [options.appearance=undefined] The appearance used to render the primitive. - * @param {Boolean} [options.vertexCacheOptimize=true] When true, geometry vertices are optimized for the pre- and post-vertex-shader caches. + * @param {Boolean} [options.vertexCacheOptimize=true] When true, geometry vertices are optimized for the pre and post-vertex-shader caches. * @param {Boolean} [options.releaseGeometryInstances=true] When true, the primitive does not keep a reference to the input geometryInstances to save memory. - * @param {Boolean} [options.allowColumbusView=true] When true, each geometry instance is prepared for rendering in Columbus view and 2D. + * @param {Boolean} [options.allow3DOnly=false] When true, each geometry instance will only be rendered in 3D. * * @example * // 1. Draw a translucent ellipse on the surface with a checkerboard pattern @@ -196,7 +196,7 @@ define([ this._releaseGeometryInstances = defaultValue(options.releaseGeometryInstances, true); // When true, geometry is transformed to world coordinates even if there is a single // geometry or all geometries are in the same reference frame. - this._allowColumbusView = defaultValue(options.allowColumbusView, true); + this._allow3DOnly = defaultValue(options.allow3DOnly, false); this._boundingSphere = undefined; this._boundingSphere2D = undefined; this._perInstanceAttributes = undefined; @@ -309,7 +309,7 @@ define([ } function transformToWorldCoordinates(primitive, instances) { - var toWorld = primitive._allowColumbusView; + var toWorld = !primitive._allow3DOnly; var length = instances.length; var i; @@ -414,7 +414,7 @@ define([ transformToWorldCoordinates(primitive, instances); // Clip to IDL - if (primitive._allowColumbusView) { + if (!primitive._allow3DOnly) { for (i = 0; i < length; ++i) { GeometryPipeline.wrapLongitude(instances[i].geometry); } @@ -439,7 +439,7 @@ define([ var geometry = GeometryPipeline.combine(instances); // Split positions for GPU RTE - if (primitive._allowColumbusView) { + if (!primitive._allow3DOnly) { // Compute 2D positions GeometryPipeline.projectTo2D(geometry, projection); @@ -566,7 +566,7 @@ define([ function createColumbusViewShader(primitive, vertexShaderSource) { var attributes; - if (primitive._allowColumbusView) { + if (!primitive._allow3DOnly) { attributes = 'attribute vec3 position2DHigh;\n' + 'attribute vec3 position2DLow;\n'; @@ -577,7 +577,7 @@ define([ var computePosition = '\nvec4 czm_computePosition()\n' + '{\n'; - if (primitive._allowColumbusView) { + if (!primitive._allow3DOnly) { computePosition += ' vec4 p;\n' + ' if (czm_morphTime == 1.0)\n' + @@ -665,11 +665,8 @@ define([ if (!this.show || ((typeof this.geometryInstances === 'undefined') && (this._va.length === 0)) || (typeof this.appearance === 'undefined') || - (frameState.mode !== SceneMode.SCENE3D && !this._allowColumbusView)) { - return; - } - - if (!frameState.passes.color && !frameState.passes.pick) { + (frameState.mode !== SceneMode.SCENE3D && this._allow3DOnly) || + (!frameState.passes.color && !frameState.passes.pick)) { return; } @@ -683,7 +680,7 @@ define([ if (this._va.length === 0) { var projection = frameState.scene2D.projection; - var instances = (this.geometryInstances instanceof Array) ? this.geometryInstances : [this.geometryInstances]; + var instances = (Array.isArray(this.geometryInstances)) ? this.geometryInstances : [this.geometryInstances]; // Copy instances first since most pipeline operations modify the geometry and instance in-place. length = instances.length; var insts = new Array(length); @@ -695,7 +692,7 @@ define([ this._attributeIndices = GeometryPipeline.createAttributeIndices(geometries[0]); this._boundingSphere = geometries[0].boundingSphere; - if (this._allowColumbusView && typeof this._boundingSphere !== 'undefined') { + if (!this._allow3DOnly && typeof this._boundingSphere !== 'undefined') { this._boundingSphere2D = BoundingSphere.projectTo2D(this._boundingSphere, projection); } diff --git a/Source/Scene/createTangentSpaceDebugPrimitive.js b/Source/Scene/createTangentSpaceDebugPrimitive.js index f1ba8ba0167e..635cf8262586 100644 --- a/Source/Scene/createTangentSpaceDebugPrimitive.js +++ b/Source/Scene/createTangentSpaceDebugPrimitive.js @@ -1,16 +1,20 @@ /*global define*/ define([ + '../Core/defaultValue', '../Core/DeveloperError', '../Core/ColorGeometryInstanceAttribute', '../Core/GeometryInstance', '../Core/GeometryPipeline', + '../Core/Matrix4', './Primitive', './PerInstanceColorAppearance' ], function( + defaultValue, DeveloperError, ColorGeometryInstanceAttribute, GeometryInstance, GeometryPipeline, + Matrix4, Primitive, PerInstanceColorAppearance) { "use strict"; @@ -23,8 +27,8 @@ define([ * * @exports createTangentSpaceDebugPrimitive * - * @param {Geometry} geometry The Geometry instance with the attribute. - * @param {Number} [length=10000.0] The length of each line segment in meters. This can be negative to point the vector in the opposite direction. + * @param {Geometry} options.geometry The Geometry instance with the attribute. + * @param {Number} [options.length=10000.0] The length of each line segment in meters. This can be negative to point the vector in the opposite direction. * @param {Matrix4} [options.modelMatrix=Matrix4.IDENTITY] The model matrix that transforms to transform the geometry from model to world coordinates. * * @returns {Primitive} A new Primitive instance with geometry for the vectors. @@ -40,17 +44,18 @@ define([ * })); */ function createTangentSpaceDebugPrimitive(options) { + options = defaultValue(options, defaultValue.EMPTY_OBJECT); + var instances = []; var geometry = options.geometry; - if (typeof geometry === 'undefined') { - throw new DeveloperError('options is required.'); + throw new DeveloperError('options.geometry is required.'); } var attributes = geometry.attributes; - var modelMatrix = options.modelMatrix; - var length = options.length; + var modelMatrix = Matrix4.clone(defaultValue(options.modelMatrix, Matrix4.IDENTITY)); + var length = defaultValue(options.length, 10000.0); if (typeof attributes.normal !== 'undefined') { instances.push(new GeometryInstance({ diff --git a/Source/Widgets/BaseLayerPicker/BaseLayerPicker.js b/Source/Widgets/BaseLayerPicker/BaseLayerPicker.js index 973e9902312c..bcd60e2d9d13 100644 --- a/Source/Widgets/BaseLayerPicker/BaseLayerPicker.js +++ b/Source/Widgets/BaseLayerPicker/BaseLayerPicker.js @@ -47,8 +47,7 @@ define([ * // and in the body, include: <div id="baseLayerPickerContainer"></div> * * //Create the list of available providers we would like the user to select from. - * //This example uses 4, OpenStreetMap, The Black Marble, and a single, non-streaming world image, - * //and an array of ImageryLayers with the Bing satellite layer overlayed with the Black Marble layer + * //This example uses 3, OpenStreetMap, The Black Marble, and a single, non-streaming world image. * var providerViewModels = []; * providerViewModels.push(new ImageryProviderViewModel({ * name : 'Open\u00adStreet\u00adMap', @@ -87,33 +86,6 @@ define([ * } * })); * - * providerViewModels.push(ImageryProviderViewModel.fromConstants({ - * name : 'Bing areal with black marble overlay', - * iconUrl : require.toUrl('../Images/ImageryProviders/blackMarble.png'), - * tooltip : 'Bing Areal imagery with the lights of cities and villages trace the outlines of civilization in this global view of the \ -Earth at night as seen by NASA/NOAA\'s Suomi NPP satellite.', - * creationFunction : function() { - * var bing = new BingMapsImageryProvider({ - * url : 'http://dev.virtualearth.net', - * mapStyle : BingMapsStyle.AERIAL, - * proxy : proxyIfNeeded - * }); - * - * var black = new TileMapServiceImageryProvider({ - * url : 'http://cesium.agi.com/blackmarble', - * maximumLevel : 8, - * credit : 'Black Marble imagery courtesy NASA Earth Observatory', - * proxy : proxyIfNeeded, - * }); - * - * var bingLayer = new ImageryLayer(bing); - * var blackLayer = new ImageryLayer(black); - * blackLayer.alpha = 0.4; - * - * return [ bingLayer, blackLayer ]; - * } - * })); - * * //Finally, create the actual widget using our view models. * var layers = centralBody.getImageryLayers(); * var baseLayerPicker = new BaseLayerPicker('baseLayerPickerContainer', layers, providerViewModels); @@ -236,4 +208,4 @@ Earth at night as seen by NASA/NOAA\'s Suomi NPP satellite.', }; return BaseLayerPicker; -}); +}); \ No newline at end of file diff --git a/Source/Widgets/BaseLayerPicker/BaseLayerPickerViewModel.js b/Source/Widgets/BaseLayerPicker/BaseLayerPickerViewModel.js index 032372d6d26c..bfa565d5fc5f 100644 --- a/Source/Widgets/BaseLayerPicker/BaseLayerPickerViewModel.js +++ b/Source/Widgets/BaseLayerPicker/BaseLayerPickerViewModel.js @@ -3,15 +3,11 @@ define([ '../../Core/defineProperties', '../../Core/DeveloperError', '../createCommand', - '../../Scene/ImageryLayer', - '../../Scene/ImageryProvider', '../../ThirdParty/knockout' ], function( defineProperties, DeveloperError, createCommand, - ImageryLayer, - ImageryProvider, knockout) { "use strict"; @@ -160,4 +156,4 @@ define([ }); return BaseLayerPickerViewModel; -}); +}); \ No newline at end of file diff --git a/Specs/Scene/PrimitiveSpec.js b/Specs/Scene/PrimitiveSpec.js index a6189e7b523d..6b98c5f0b3fa 100644 --- a/Specs/Scene/PrimitiveSpec.js +++ b/Specs/Scene/PrimitiveSpec.js @@ -157,7 +157,7 @@ defineSuite([ var primitive = new Primitive({ geometryInstances : [extentInstance1, extentInstance2], appearance : new PerInstanceColorAppearance(), - allowColumbusView : false + allow3DOnly : true }); var commands = []; @@ -176,7 +176,7 @@ defineSuite([ var primitive = new Primitive({ geometryInstances : [extentInstance1, extentInstance2], appearance : new PerInstanceColorAppearance(), - allowColumbusView : false + allow3DOnly : true }); frameState.passes.color = false; @@ -192,11 +192,11 @@ defineSuite([ primitive = primitive && primitive.destroy(); }); - it('does not render when allowColumbusView is false and the scene mode is SCENE2D', function() { + it('does not render when allow3DOnly is true and the scene mode is SCENE2D', function() { var primitive = new Primitive({ geometryInstances : [extentInstance1, extentInstance2], appearance : new PerInstanceColorAppearance(), - allowColumbusView : false + allow3DOnly : true }); frameState.mode = SceneMode.SCENE2D; @@ -209,11 +209,11 @@ defineSuite([ primitive = primitive && primitive.destroy(); }); - it('does not render when allowColumbusView is false and the scene mode is COLUMBUS_VIEW', function() { + it('does not render when allow3DOnly is true and the scene mode is COLUMBUS_VIEW', function() { var primitive = new Primitive({ geometryInstances : [extentInstance1, extentInstance2], appearance : new PerInstanceColorAppearance(), - allowColumbusView : false + allow3DOnly : true }); frameState.mode = SceneMode.COLUMBUS_VIEW; @@ -226,11 +226,11 @@ defineSuite([ primitive = primitive && primitive.destroy(); }); - it('renders in Columbus view when allowColumbusView is true', function() { + it('renders in Columbus view when allow3DOnly is false', function() { var primitive = new Primitive({ geometryInstances : [extentInstance1, extentInstance2], appearance : new PerInstanceColorAppearance(), - allowColumbusView : true + allow3DOnly : false }); frameState.mode = SceneMode.COLUMBUS_VIEW; @@ -263,11 +263,11 @@ defineSuite([ primitive = primitive && primitive.destroy(); }); - it('renders in 2D when allowColumbusView is true', function() { + it('renders in 2D when allow3DOnly is false', function() { var primitive = new Primitive({ geometryInstances : [extentInstance1, extentInstance2], appearance : new PerInstanceColorAppearance(), - allowColumbusView : true + allow3DOnly : false }); frameState.mode = SceneMode.SCENE2D; @@ -310,7 +310,7 @@ defineSuite([ var primitive = new Primitive({ geometryInstances : [extentInstance1, extentInstance2], appearance : new PerInstanceColorAppearance(), - allowColumbusView : false + allow3DOnly : true }); frameState.camera.controller.viewExtent(extent1); @@ -341,7 +341,7 @@ defineSuite([ var primitive = new Primitive({ geometryInstances : [extentInstance1, extentInstance2], appearance : new PerInstanceColorAppearance(), - allowColumbusView : false + allow3DOnly : true }); frameState.camera.controller.viewExtent(extent1); @@ -377,7 +377,7 @@ defineSuite([ var primitive = new Primitive({ geometryInstances : [extentInstance1, extentInstance2], appearance : new PerInstanceColorAppearance(), - allowColumbusView : false + allow3DOnly : true }); primitive.update(context, frameState, []); @@ -397,7 +397,7 @@ defineSuite([ var primitive = new Primitive({ geometryInstances : extentInstance1, appearance : new PerInstanceColorAppearance(), - allowColumbusView : false + allow3DOnly : true }); frameState.camera.controller.viewExtent(extent1); @@ -429,7 +429,7 @@ defineSuite([ var primitive = new Primitive({ geometryInstances : extentInstance1, appearance : new PerInstanceColorAppearance(), - allowColumbusView : false + allow3DOnly : true }); frameState.camera.controller.viewExtent(extent1); @@ -458,7 +458,7 @@ defineSuite([ var primitive = new Primitive({ geometryInstances : [extentInstance1, extentInstance2], appearance : new PerInstanceColorAppearance(), - allowColumbusView : false + allow3DOnly : true }); frameState.camera.controller.viewExtent(extent1); @@ -513,7 +513,7 @@ defineSuite([ it('shader validation', function() { var primitive = new Primitive({ geometryInstances : [extentInstance1, extentInstance2], - allowColumbusView : false, + allow3DOnly : true, appearance : new MaterialAppearance({ materialSupport : MaterialAppearance.MaterialSupport.ALL }) @@ -528,7 +528,7 @@ defineSuite([ var primitive = new Primitive({ geometryInstances : extentInstance1, appearance : new PerInstanceColorAppearance(), - allowColumbusView : false + allow3DOnly : true }); primitive.update(context, frameState, []); @@ -545,7 +545,7 @@ defineSuite([ var primitive = new Primitive({ geometryInstances : extentInstance1, appearance : new PerInstanceColorAppearance(), - allowColumbusView : false + allow3DOnly : true }); primitive.update(context, frameState, []); @@ -561,7 +561,7 @@ defineSuite([ var primitive = new Primitive({ geometryInstances : extentInstance1, appearance : new PerInstanceColorAppearance(), - allowColumbusView : false + allow3DOnly : true }); primitive.update(context, frameState, []); @@ -577,7 +577,7 @@ defineSuite([ var primitive = new Primitive({ geometryInstances : extentInstance1, appearance : new PerInstanceColorAppearance(), - allowColumbusView : false + allow3DOnly : true }); expect(function() { @@ -591,7 +591,7 @@ defineSuite([ var primitive = new Primitive({ geometryInstances : extentInstance1, appearance : new PerInstanceColorAppearance(), - allowColumbusView : false + allow3DOnly : true }); primitive.update(context, frameState, []); From bfbb8cc3154cb6507c9503afbf9a1faaf776baf9 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Wed, 10 Jul 2013 19:43:53 -0400 Subject: [PATCH 304/306] Fix faceforward for apearances with materials. --- Source/Scene/Appearance.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Source/Scene/Appearance.js b/Source/Scene/Appearance.js index 161461c4d09b..f473d8d3d1e3 100644 --- a/Source/Scene/Appearance.js +++ b/Source/Scene/Appearance.js @@ -76,13 +76,14 @@ define([ * @return String The full GLSL fragment shader source. */ Appearance.prototype.getFragmentShaderSource = function() { - var flat = this.flat ? '#define FLAT \n#line 0 \n' : '#line 0 \n'; - var faceForward = this.faceForward ? '#define FACE_FORWARD \n#line 0 \n' : '#line 0 \n'; + var flat = this.flat ? '#define FLAT 1\n#line 0 \n' : '#line 0 \n'; + var faceForward = this.faceForward ? '#define FACE_FORWARD 1\n#line 0 \n' : '#line 0 \n'; if (typeof this.material !== 'undefined') { return '#line 0\n' + this.material.shaderSource + flat + + faceForward + this.fragmentShaderSource; } From 4d476397f3342fe616abaf9918695082f9db7ef8 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Wed, 10 Jul 2013 19:46:18 -0400 Subject: [PATCH 305/306] Update doc. --- Source/Scene/Primitive.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index 759e4d4aacbf..7777864d8219 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -66,7 +66,7 @@ define([ * @alias Primitive * @constructor * - * @param {Array} [options.geometryInstances=undefined] The geometry instances - or a single geometry instance - to render. + * @param {Array|GeometryInstance} [options.geometryInstances=undefined] The geometry instances - or a single geometry instance - to render. * @param {Appearance} [options.appearance=undefined] The appearance used to render the primitive. * @param {Boolean} [options.vertexCacheOptimize=true] When true, geometry vertices are optimized for the pre and post-vertex-shader caches. * @param {Boolean} [options.releaseGeometryInstances=true] When true, the primitive does not keep a reference to the input geometryInstances to save memory. @@ -143,8 +143,6 @@ define([ * @type Array * * @default undefined - * - * @readonly */ this.geometryInstances = options.geometryInstances; From 0d3eb09b52711d3eeda3263a8b657e49213ba83b Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 11 Jul 2013 14:30:24 -0400 Subject: [PATCH 306/306] Fix per-instance attributes by using any object for the id (not just a string or number). --- Source/Scene/Primitive.js | 110 ++++++++++++++++++++--------------- Specs/Scene/PrimitiveSpec.js | 16 ----- 2 files changed, 62 insertions(+), 64 deletions(-) diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index 7777864d8219..4711e8c65a4a 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -103,7 +103,7 @@ define([ * CesiumMath.toRadians(-100.0), * CesiumMath.toRadians(40.0)) * }), - * id : 'object returned when this instance is picked and to get/set per-instance attributes', + * id : 'extent', * attribute : { * color : new ColorGeometryInstanceAttribute(0.0, 1.0, 1.0, 0.5) * } @@ -115,7 +115,7 @@ define([ * }), * modelMatrix : Matrix4.multiplyByTranslation(Transforms.eastNorthUpToFixedFrame( * ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-95.59777, 40.03883))), new Cartesian3(0.0, 0.0, 500000.0)), - * id : 'object returned when this instance is picked and to get/set per-instance attributes', + * id : 'ellipsoid', * attribute : { * color : ColorGeometryInstanceAttribute.fromColor(Color.AQUA) * } @@ -197,8 +197,8 @@ define([ this._allow3DOnly = defaultValue(options.allow3DOnly, false); this._boundingSphere = undefined; this._boundingSphere2D = undefined; - this._perInstanceAttributes = undefined; - this._perInstanceAttributesCache = {}; + this._perInstanceAttributes = {}; + this._lastPerInstanceAttributeIndex = 0; this._va = []; this._attributeIndices = undefined; @@ -488,7 +488,8 @@ define([ } function computePerInstanceAttributeIndices(instances, vertexArrays, attributeIndices) { - var indices = {}; + var ids = []; + var indices = []; var names = getCommonPerInstanceAttributeNames(instances); var length = instances.length; @@ -518,12 +519,16 @@ define([ } } - if (typeof indices[instance.id] === 'undefined') { - indices[instance.id] = {}; + if (typeof ids[i] === 'undefined') { + ids[i] = instance.id; } - if (typeof indices[instance.id][name] === 'undefined') { - indices[instance.id][name] = { + if (typeof indices[i] === 'undefined') { + indices[i] = {}; + } + + if (typeof indices[i][name] === 'undefined') { + indices[i][name] = { dirty : false, value : instance.attributes[name].value, indices : [] @@ -537,7 +542,7 @@ define([ var count; if (offset + tempVertexCount < size) { count = tempVertexCount; - indices[instance.id][name].indices.push({ + indices[i][name].indices.push({ attribute : attribute, offset : offset, count : count @@ -545,7 +550,7 @@ define([ offsets[name] = offset + tempVertexCount; } else { count = size - offset; - indices[instance.id][name].indices.push({ + indices[i][name].indices.push({ attribute : attribute, offset : offset, count : count @@ -559,7 +564,10 @@ define([ } } - return indices; + return { + ids : ids, + indices : indices + }; } function createColumbusViewShader(primitive, vertexShaderSource) { @@ -791,37 +799,36 @@ define([ // Update per-instance attributes if (this._perInstanceAttributes._dirty) { - var perInstance = this._perInstanceAttributes; - for (var id in perInstance) { - if (perInstance.hasOwnProperty(id) && id !== '_dirty') { - var perInstanceAttributes = perInstance[id]; - for (var name in perInstanceAttributes) { - if (perInstanceAttributes.hasOwnProperty(name)) { - var attribute = perInstanceAttributes[name]; - if (attribute.dirty) { - var value = attribute.value; - var indices = attribute.indices; - length = indices.length; - for (i = 0; i < length; ++i) { - var index = indices[i]; - var offset = index.offset; - var count = index.count; - - var vaAttribute = index.attribute; - var componentDatatype = vaAttribute.componentDatatype; - var componentsPerAttribute = vaAttribute.componentsPerAttribute; - - var typedArray = componentDatatype.createTypedArray(count * componentsPerAttribute); - for (var j = 0; j < count; ++j) { - typedArray.set(value, j * componentsPerAttribute); - } - - var offsetInBytes = offset * componentsPerAttribute * componentDatatype.sizeInBytes; - vaAttribute.vertexBuffer.copyFromArrayView(typedArray, offsetInBytes); + var perInstanceIndices = this._perInstanceAttributes.indices; + length = perInstanceIndices.length; + for (i = 0; i < length; ++i) { + var perInstanceAttributes = perInstanceIndices[i]; + for (var name in perInstanceAttributes) { + if (perInstanceAttributes.hasOwnProperty(name)) { + var attribute = perInstanceAttributes[name]; + if (attribute.dirty) { + var value = attribute.value; + var indices = attribute.indices; + var indicesLength = indices.length; + for (var j = 0; j < indicesLength; ++j) { + var index = indices[j]; + var offset = index.offset; + var count = index.count; + + var vaAttribute = index.attribute; + var componentDatatype = vaAttribute.componentDatatype; + var componentsPerAttribute = vaAttribute.componentsPerAttribute; + + var typedArray = componentDatatype.createTypedArray(count * componentsPerAttribute); + for (var k = 0; k < count; ++k) { + typedArray.set(value, k * componentsPerAttribute); } - attribute.dirty = false; + var offsetInBytes = offset * componentsPerAttribute * componentDatatype.sizeInBytes; + vaAttribute.vertexBuffer.copyFromArrayView(typedArray, offsetInBytes); } + + attribute.dirty = false; } } } @@ -893,20 +900,27 @@ define([ throw new DeveloperError('id is required'); } - var cachedObject = this._perInstanceAttributesCache[id]; - if (typeof cachedObject !== 'undefined') { - return cachedObject; - } - if (typeof this._perInstanceAttributes === 'undefined') { throw new DeveloperError('must call update before calling getGeometryInstanceAttributes'); } - var perInstanceAttributes = this._perInstanceAttributes[id]; - if (typeof perInstanceAttributes === 'undefined') { + var index = -1; + var lastIndex = this._lastPerInstanceAttributeIndex; + var ids = this._perInstanceAttributes.ids; + var length = ids.length; + for (var i = 0; i < length; ++i) { + var curIndex = (lastIndex + i) % length; + if (id === ids[curIndex]) { + index = curIndex; + break; + } + } + + if (index === -1) { return undefined; } + var perInstanceAttributes = this._perInstanceAttributes.indices[index]; var attributes = {}; for (var name in perInstanceAttributes) { @@ -918,7 +932,7 @@ define([ } } - this._perInstanceAttributesCache[id] = attributes; + this._lastPerInstanceAttributeIndex = index; return attributes; }; diff --git a/Specs/Scene/PrimitiveSpec.js b/Specs/Scene/PrimitiveSpec.js index 6b98c5f0b3fa..eb3bc352d6f5 100644 --- a/Specs/Scene/PrimitiveSpec.js +++ b/Specs/Scene/PrimitiveSpec.js @@ -557,22 +557,6 @@ defineSuite([ primitive = primitive && primitive.destroy(); }); - it('getGeometryInstanceAttributes caches results', function() { - var primitive = new Primitive({ - geometryInstances : extentInstance1, - appearance : new PerInstanceColorAppearance(), - allow3DOnly : true - }); - - primitive.update(context, frameState, []); - - var attributes1 = primitive.getGeometryInstanceAttributes('extent1'); - var attributes2 = primitive.getGeometryInstanceAttributes('extent1'); - expect(attributes1).toBe(attributes2); - - primitive = primitive && primitive.destroy(); - }); - it('getGeometryInstanceAttributes throws if update was not called', function() { var primitive = new Primitive({ geometryInstances : extentInstance1,