Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compress Primitive normals #2213

Merged
merged 23 commits into from
Oct 23, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
0b2c9d3
Add GeometryPipeline.compressNormals.
bagnell Oct 17, 2014
a6e7003
Add GeometryPipeline.compressNormals tests.
bagnell Oct 17, 2014
0328008
Compress Primitive normals, tangents, and binormals. Pack when possible.
bagnell Oct 18, 2014
29b936c
Fix DebugAppearance specs.
bagnell Oct 18, 2014
30b2a90
Merge branch 'octEncoding' into compressNormals
bagnell Oct 18, 2014
16668af
Use oct encoded Primitive normals and texture coordinates stored in a…
bagnell Oct 19, 2014
b15632b
Fix modified shader when compressing texture coordinates.
bagnell Oct 19, 2014
1e0f128
Merge branch 'master' into compressNormals
bagnell Oct 20, 2014
37136bf
If normal, tangent, and binormal are present, then compess to two flo…
bagnell Oct 20, 2014
4fd2003
Revert back to storing a single normal as two floats. Fix the rest of…
bagnell Oct 21, 2014
5d096bf
Clean up code modifying vertex shader.
bagnell Oct 21, 2014
e7224cc
Fix Sandcastle examples.
bagnell Oct 21, 2014
7aee555
Remove unused code.
bagnell Oct 21, 2014
c0c1a63
Merge branch 'octDecoding' into compressNormals
bagnell Oct 22, 2014
4298be9
Merge branch 'master' into compressNormals
bagnell Oct 22, 2014
ce4e1a8
Re-add compressing normals to a single float.
bagnell Oct 22, 2014
4cfbef1
Add doc and error checking.
bagnell Oct 22, 2014
e3daa49
Fix GeometryPipeline and BuiltinFunctions tests.
bagnell Oct 22, 2014
8630004
Add tests for the new oct encode/decode functions.
bagnell Oct 22, 2014
f706765
Update Primitive default construction test.
bagnell Oct 22, 2014
39e817e
Merge remote-tracking branch 'origin/master' into compressNormals
pjcozzi Oct 22, 2014
6fd4ea6
Updates from review.
bagnell Oct 22, 2014
20658ad
Update tests.
bagnell Oct 22, 2014
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Apps/Sandcastle/gallery/Geometry and Appearances.html
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,8 @@
geometry : new Cesium.WallGeometry({
positions : positions,
maximumHeights : maximumHeights,
minimumHeights : minimumHeights
minimumHeights : minimumHeights,
vertexFormat : Cesium.PerInstanceColorAppearance.VERTEX_FORMAT
}),
attributes : {
color : Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.fromRandom({alpha : 0.7}))
Expand Down
12 changes: 8 additions & 4 deletions Apps/Sandcastle/gallery/Material.html
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,13 @@
positions : Cesium.Cartesian3.fromDegreesArrayHeights([
-95.5, 50.0, 300000.0,
-90.5, 50.0, 300000.0
])
]),
vertexFormat : Cesium.MaterialAppearance.MaterialSupport.TEXTURED.vertexFormat
})
}),
appearance : new Cesium.MaterialAppearance({
material : Cesium.Material.fromType('Checkerboard')
material : Cesium.Material.fromType('Checkerboard'),
materialSupport : Cesium.MaterialAppearance.MaterialSupport.TEXTURED
})
}));

Expand All @@ -52,11 +54,13 @@
positions : Cesium.Cartesian3.fromDegreesArrayHeights([
-100.5, 50.0, 300000.0,
-95.5, 50.0, 300000.0
])
]),
vertexFormat : Cesium.MaterialAppearance.MaterialSupport.TEXTURED.vertexFormat
})
}),
appearance : new Cesium.MaterialAppearance({
material : Cesium.Material.fromType('Stripe')
material : Cesium.Material.fromType('Stripe'),
materialSupport : Cesium.MaterialAppearance.MaterialSupport.TEXTURED
})
}));
//Sandcastle_End
Expand Down
9 changes: 6 additions & 3 deletions Apps/Sandcastle/gallery/Wall.html
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@
-90.0, 44.0
]),
maximumHeight : 200000.0,
minimumHeight : 100000.0
minimumHeight : 100000.0,
vertexFormat : Cesium.PerInstanceColorAppearance.VERTEX_FORMAT
}),
attributes : {
color : Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.RED)
Expand All @@ -62,7 +63,8 @@
-107.0, 40.0,
-107.0, 43.0
]),
maximumHeight : 100000.0
maximumHeight : 100000.0,
vertexFormat : Cesium.PerInstanceColorAppearance.VERTEX_FORMAT
}),
attributes : {
color : Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.GREEN)
Expand Down Expand Up @@ -93,7 +95,8 @@
geometry : new Cesium.WallGeometry({
positions : positions,
maximumHeights: maximumHeights,
minimumHeights: minimumHeights
minimumHeights: minimumHeights,
vertexFormat : Cesium.PerInstanceColorAppearance.VERTEX_FORMAT

}),
attributes : {
Expand Down
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Change Log
* Fixed a bug that caused non-base imagery layers with a limited `rectangle` to be stretched to the edges of imagery tiles. [#416](https://github.com/AnalyticalGraphicsInc/cesium/issues/416)
* Fixed rendering polylines with duplicate positions. [#898](https://github.com/AnalyticalGraphicsInc/cesium/issues/898)
* Added support to the `CesiumTerrainProvider` for handling terrain tiles that define more than 64k vertices.
* Added `Primitive.compressVertices`. When true, the geometry vertices are compressed, which will save memory.
* Upgraded topojson from 1.6.8 to 1.6.18.

### 1.2 - 2014-10-01
Expand Down
119 changes: 118 additions & 1 deletion Source/Core/GeometryPipeline.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ define([
'./Math',
'./Matrix3',
'./Matrix4',
'./Oct',
'./Plane',
'./PrimitiveType',
'./Tipsify'
Expand All @@ -44,6 +45,7 @@ define([
CesiumMath,
Matrix3,
Matrix4,
Oct,
Plane,
PrimitiveType,
Tipsify) {
Expand Down Expand Up @@ -275,7 +277,11 @@ define([
'normal',
'st',
'binormal',
'tangent'
'tangent',

// From compressing normals
'stCompressedNormals',
'compressedNormals'
];

var attributes = geometry.attributes;
Expand Down Expand Up @@ -1301,6 +1307,117 @@ define([
return geometry;
};

var scratchPacked = new Cartesian2();
var toEncode1 = new Cartesian3();
var toEncode2 = new Cartesian3();
var toEncode3 = new Cartesian3();

/**
* Compresses and packs geometry normal attribute values to save memory.
*
* @param {Geometry} geometry The geometry to modify.
* @returns {Geometry} The modified <code>geometry</code> argument, with its normals compressed and packed.
*
* @example
* geometry = Cesium.GeometryPipeline.compressNormals(geometry);
*/
GeometryPipeline.compressNormals = function(geometry) {
//>>includeStart('debug', pragmas.debug);
if (!defined(geometry)) {
throw new DeveloperError('geometry is required.');
}
//>>includeEnd('debug');

var normalAttribute = geometry.attributes.normal;
if (!defined(normalAttribute)) {
return geometry;
}

var stAttribute = geometry.attributes.st;
var tangentAttribute = geometry.attributes.tangent;
var binormalAttribute = geometry.attributes.binormal;

var normals = normalAttribute.values;
var st;
var tangents;
var binormals;


if (defined(stAttribute)) {
st = stAttribute.values;
}
if (defined(tangentAttribute)) {
tangents = tangentAttribute.values;
}
if (binormalAttribute) {
binormals = binormalAttribute.values;
}

var length = normals.length;
var compressedLength = length / 3.0;
var numComponents = 1.0;
numComponents += defined(st) ? 2.0 : 0.0;
numComponents += defined(tangents) || defined(binormals) ? 1.0 : 0.0;
compressedLength *= numComponents;
var compressedNormals = new Float32Array(compressedLength);

var normalIndex = 0;
var stIndex = 0;
var tangentsIndex = 0;

for (var i = 0; i < length; i += 3) {
if (defined(st)) {
compressedNormals[normalIndex++] = st[stIndex++];
compressedNormals[normalIndex++] = st[stIndex++];
}

if (defined(tangents) && defined(binormals)) {
Cartesian3.fromArray(normals, i, toEncode1);
Cartesian3.fromArray(tangents, i, toEncode2);
Cartesian3.fromArray(binormals, i, toEncode3);

Oct.pack(toEncode1, toEncode2, toEncode3, scratchPacked);
compressedNormals[normalIndex++] = scratchPacked.x;
compressedNormals[normalIndex++] = scratchPacked.y;
} else {
Cartesian3.fromArray(normals, i, toEncode1);
compressedNormals[normalIndex++] = Oct.encodeFloat(toEncode1);

if (defined(tangents)) {
Cartesian3.fromArray(tangents, i, toEncode1);
compressedNormals[normalIndex++] = Oct.encodeFloat(toEncode1);
}

if (defined(binormals)) {
Cartesian3.fromArray(binormals, i, toEncode1);
compressedNormals[normalIndex++] = Oct.encodeFloat(toEncode1);
}
}
}

var attributeName = defined(st) ? 'stCompressedNormals' : 'compressedNormals';
geometry.attributes[attributeName] = new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : numComponents,
values : compressedNormals
});
delete geometry.attributes.normal;

if (defined(st)) {
delete geometry.attributes.st;
}

if (defined(tangents)) {
delete geometry.attributes.tangent;
}

if (defined(binormals)) {
delete geometry.attributes.binormal;
}

return geometry;
};

function indexTriangles(geometry) {
if (defined(geometry.indices)) {
return geometry;
Expand Down
94 changes: 92 additions & 2 deletions Source/Core/Oct.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,20 +121,110 @@ define([
};

/**
* Decodes a unit-length vector in 'oct' encoding to a normalized 3-component vector.
* Decodes a unit-length vector in 'oct' encoding packed in a floating-point number to a normalized 3-component vector.
*
* @param {Number} value The oct-encoded unit length vector stored as a single floating-point number.
* @param {Cartesian3} result The decoded and normalized vector
* @returns {Cartesian3} The decoded and normalized vector.
*
* @exception {DeveloperError} value must be defined.
* @exception {DeveloperError} result must be defined.
*/
Oct.decodeFloat = function(value, result) {
//>>includeStart('debug', pragmas.debug);
if (!defined(value)) {
throw new DeveloperError('value is required.');
}
//>>includeEnd('debug');

var temp = value / 256.0;
var x = Math.floor(temp);
var y = (temp - x) * 256.0;

return Oct.decode(x, y, result);
};

/**
* Encodes three normalized vectors into 6 SNORM values in the range of [0-255] following the 'oct' encoding and
* packs those into two floating-point numbers.
*
* @param {Cartesian3} v1 A normalized vector to be compressed.
* @param {Cartesian3} v2 A normalized vector to be compressed.
* @param {Cartesian3} v3 A normalized vector to be compressed.
* @param {Cartesian2} result The 'oct' encoded vectors packed into two floating-point numbers.
* @returns {Cartesian2} The 'oct' encoded vectors packed into two floating-point numbers.
*
* @exception {DeveloperError} v1 must be defined.
* @exception {DeveloperError} v2 must be defined.
* @exception {DeveloperError} v3 must be defined.
* @exception {DeveloperError} result must be defined.
*/
Oct.pack = function(v1, v2, v3, result) {
//>>includeStart('debug', pragmas.debug);
if (!defined(v1)) {
throw new DeveloperError('v1 is required.');
}
if (!defined(v2)) {
throw new DeveloperError('v2 is required.');
}
if (!defined(v3)) {
throw new DeveloperError('v3 is required.');
}
if (!defined(result)) {
throw new DeveloperError('result is required.');
}
//>>includeEnd('debug');

var encoded1 = Oct.encodeFloat(v1);
var encoded2 = Oct.encodeFloat(v2);

var encoded3 = Oct.encode(v3, scratchEncodeCart2);
result.x = 65536.0 * encoded3.x + encoded1;
result.y = 65536.0 * encoded3.y + encoded2;
return result;
};

/**
* Decodes three unit-length vectors in 'oct' encoding packed into a floating-point number to a normalized 3-component vector.
*
* @param {Cartesian2} packed The three oct-encoded unit length vectors stored as two floating-point number.
* @param {Cartesian3} v1 One decoded and normalized vector.
* @param {Cartesian3} v2 One decoded and normalized vector.
* @param {Cartesian3} v3 One decoded and normalized vector.
*
* @exception {DeveloperError} packed must be defined.
* @exception {DeveloperError} v1 must be defined.
* @exception {DeveloperError} v2 must be defined.
* @exception {DeveloperError} v3 must be defined.
*/
Oct.unpack = function(packed, v1, v2, v3) {
//>>includeStart('debug', pragmas.debug);
if (!defined(packed)) {
throw new DeveloperError('packed is required.');
}
if (!defined(v1)) {
throw new DeveloperError('v1 is required.');
}
if (!defined(v2)) {
throw new DeveloperError('v2 is required.');
}
if (!defined(v3)) {
throw new DeveloperError('v3 is required.');
}
//>>includeEnd('debug');

var temp = packed.x / 65536.0;
var x = Math.floor(temp);
var encodedFloat1 = (temp - x) * 65536.0;

temp = packed.y / 65536.0;
var y = Math.floor(temp);
var encodedFloat2 = (temp - y) * 65536.0;

Oct.decodeFloat(encodedFloat1, v1);
Oct.decodeFloat(encodedFloat2, v2);
Oct.decode(x, y, v3);
};

return Oct;
});
});
Loading