diff --git a/Source/Core/WallGeometry.js b/Source/Core/WallGeometry.js index 235174881047..14c298d28532 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,31 +131,35 @@ 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; var terrainHeight = 0.0; if (terrain !== undefined) { - var h = terrain[i].height; + var h = terrain[i/3].height; if (!isNaN(h)) { terrainHeight = h; } } - 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; } /** 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); }); });