Skip to content

Commit ab82ad4

Browse files
committed
Merge pull request #3191 from AnalyticalGraphicsInc/primitive-updates
Primitive RTC updates
2 parents ebc9466 + 38e5b91 commit ab82ad4

File tree

3 files changed

+174
-33
lines changed

3 files changed

+174
-33
lines changed

Source/Scene/GroundPrimitive.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -511,7 +511,7 @@ define([
511511

512512
var context = frameState.context;
513513

514-
var vs = Primitive._createColumbusViewShader(ShadowVolumeVS, frameState.scene3DOnly);
514+
var vs = Primitive._modifyShaderPosition(primitive, ShadowVolumeVS, frameState.scene3DOnly);
515515
vs = Primitive._appendShowToShader(primitive._primitive, vs);
516516

517517
var fs = ShadowVolumeFS;

Source/Scene/Primitive.js

+82-29
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/*global define*/
22
define([
33
'../Core/BoundingSphere',
4+
'../Core/Cartesian3',
45
'../Core/clone',
56
'../Core/combine',
67
'../Core/ComponentDatatype',
@@ -34,6 +35,7 @@ define([
3435
'./SceneMode'
3536
], function(
3637
BoundingSphere,
38+
Cartesian3,
3739
clone,
3840
combine,
3941
ComponentDatatype,
@@ -266,6 +268,18 @@ define([
266268
*/
267269
this.debugShowBoundingVolume = defaultValue(options.debugShowBoundingVolume, false);
268270

271+
/**
272+
* @private
273+
*/
274+
this.rtcCenter = options.rtcCenter;
275+
this._modifiedModelView = new Matrix4();
276+
277+
//>>includeStart('debug', pragmas.debug);
278+
if (defined(this.rtcCenter) && (!defined(this.geometryInstances) || (isArray(this.geometryInstances) && this.geometryInstances !== 1))) {
279+
throw new DeveloperError('Relative-to-center rendering only supports one geometry instance.');
280+
}
281+
//>>includeEnd('debug');
282+
269283
this._translucent = undefined;
270284

271285
this._state = PrimitiveState.READY;
@@ -499,7 +513,7 @@ define([
499513

500514
var positionRegex = /attribute\s+vec(?:3|4)\s+(.*)3DHigh;/g;
501515

502-
Primitive._createColumbusViewShader = function(vertexShaderSource, scene3DOnly) {
516+
Primitive._modifyShaderPosition = function(primitive, vertexShaderSource, scene3DOnly) {
503517
var match;
504518

505519
var forwardDecl = '';
@@ -516,38 +530,58 @@ define([
516530
forwardDecl += functionName + ';\n';
517531
}
518532

519-
if (!scene3DOnly) {
520-
attributes +=
521-
'attribute vec3 ' + name + '2DHigh;\n' +
522-
'attribute vec3 ' + name + '2DLow;\n';
523-
524-
computeFunctions +=
525-
functionName + '\n' +
526-
'{\n' +
527-
' vec4 p;\n' +
528-
' if (czm_morphTime == 1.0)\n' +
529-
' {\n' +
530-
' p = czm_translateRelativeToEye(' + name + '3DHigh, ' + name + '3DLow);\n' +
531-
' }\n' +
532-
' else if (czm_morphTime == 0.0)\n' +
533-
' {\n' +
534-
' p = czm_translateRelativeToEye(' + name + '2DHigh.zxy, ' + name + '2DLow.zxy);\n' +
535-
' }\n' +
536-
' else\n' +
537-
' {\n' +
538-
' p = czm_columbusViewMorph(\n' +
539-
' czm_translateRelativeToEye(' + name + '2DHigh.zxy, ' + name + '2DLow.zxy),\n' +
540-
' czm_translateRelativeToEye(' + name + '3DHigh, ' + name + '3DLow),\n' +
541-
' czm_morphTime);\n' +
542-
' }\n' +
543-
' return p;\n' +
544-
'}\n\n';
533+
if (!defined(primitive.rtcCenter)) {
534+
// Use GPU RTE
535+
if (!scene3DOnly) {
536+
attributes +=
537+
'attribute vec3 ' + name + '2DHigh;\n' +
538+
'attribute vec3 ' + name + '2DLow;\n';
539+
540+
computeFunctions +=
541+
functionName + '\n' +
542+
'{\n' +
543+
' vec4 p;\n' +
544+
' if (czm_morphTime == 1.0)\n' +
545+
' {\n' +
546+
' p = czm_translateRelativeToEye(' + name + '3DHigh, ' + name + '3DLow);\n' +
547+
' }\n' +
548+
' else if (czm_morphTime == 0.0)\n' +
549+
' {\n' +
550+
' p = czm_translateRelativeToEye(' + name + '2DHigh.zxy, ' + name + '2DLow.zxy);\n' +
551+
' }\n' +
552+
' else\n' +
553+
' {\n' +
554+
' p = czm_columbusViewMorph(\n' +
555+
' czm_translateRelativeToEye(' + name + '2DHigh.zxy, ' + name + '2DLow.zxy),\n' +
556+
' czm_translateRelativeToEye(' + name + '3DHigh, ' + name + '3DLow),\n' +
557+
' czm_morphTime);\n' +
558+
' }\n' +
559+
' return p;\n' +
560+
'}\n\n';
561+
} else {
562+
computeFunctions +=
563+
functionName + '\n' +
564+
'{\n' +
565+
' return czm_translateRelativeToEye(' + name + '3DHigh, ' + name + '3DLow);\n' +
566+
'}\n\n';
567+
}
545568
} else {
569+
// Use RTC
570+
vertexShaderSource = vertexShaderSource.replace(/attribute\s+vec(?:3|4)\s+position3DHigh;/g, '');
571+
vertexShaderSource = vertexShaderSource.replace(/attribute\s+vec(?:3|4)\s+position3DLow;/g, '');
572+
573+
forwardDecl += 'uniform mat4 u_modifiedModelView;\n';
574+
attributes += 'attribute vec4 position;\n';
575+
546576
computeFunctions +=
547577
functionName + '\n' +
548578
'{\n' +
549-
' return czm_translateRelativeToEye(' + name + '3DHigh, ' + name + '3DLow);\n' +
579+
' return u_modifiedModelView * position;\n' +
550580
'}\n\n';
581+
582+
583+
vertexShaderSource = vertexShaderSource.replace(/czm_modelViewRelativeToEye\s+\*\s+/g, '');
584+
vertexShaderSource = vertexShaderSource.replace(/czm_modelViewProjectionRelativeToEye/g, 'czm_projection');
551585
}
552586
}
553587

@@ -1031,7 +1065,7 @@ define([
10311065
function createShaderProgram(primitive, frameState, appearance) {
10321066
var context = frameState.context;
10331067

1034-
var vs = Primitive._createColumbusViewShader(appearance.vertexShaderSource, frameState.scene3DOnly);
1068+
var vs = Primitive._modifyShaderPosition(primitive, appearance.vertexShaderSource, frameState.scene3DOnly);
10351069
vs = Primitive._appendShowToShader(primitive, vs);
10361070
vs = modifyForEncodedNormals(primitive, vs);
10371071
var fs = appearance.getFragmentShaderSource();
@@ -1090,6 +1124,12 @@ define([
10901124
}
10911125
var uniforms = combine(appearanceUniformMap, materialUniformMap);
10921126

1127+
if (defined(primitive.rtcCenter)) {
1128+
uniforms.u_modifiedModelView = function() {
1129+
return primitive._modifiedModelView;
1130+
};
1131+
}
1132+
10931133
var pass = translucent ? Pass.TRANSLUCENT : Pass.OPAQUE;
10941134

10951135
colorCommands.length = primitive._va.length * (twoPasses ? 2 : 1);
@@ -1184,6 +1224,8 @@ define([
11841224
attributes.length = 0;
11851225
}
11861226

1227+
var rtcScratch = new Cartesian3();
1228+
11871229
function updateAndQueueCommands(primitive, frameState, colorCommands, pickCommands, modelMatrix, cull, debugShowBoundingVolume, twoPasses) {
11881230
//>>includeStart('debug', pragmas.debug);
11891231
if (frameState.mode !== SceneMode.SCENE3D && !Matrix4.equals(modelMatrix, Matrix4.IDENTITY)) {
@@ -1207,6 +1249,13 @@ define([
12071249
}
12081250
}
12091251

1252+
if (defined(primitive.rtcCenter)) {
1253+
var viewMatrix = frameState.camera.viewMatrix;
1254+
Matrix4.multiply(viewMatrix, primitive._modelMatrix, primitive._modifiedModelView);
1255+
Matrix4.multiplyByPoint(primitive._modifiedModelView, primitive.rtcCenter, rtcScratch);
1256+
Matrix4.setTranslation(primitive._modifiedModelView, rtcScratch, primitive._modifiedModelView);
1257+
}
1258+
12101259
var boundingSpheres;
12111260
if (frameState.mode === SceneMode.SCENE3D) {
12121261
boundingSpheres = primitive._boundingSphereWC;
@@ -1270,6 +1319,10 @@ define([
12701319
throw this._error;
12711320
}
12721321

1322+
if (defined(this.rtcCenter) && !frameState.scene3DOnly) {
1323+
throw new DeveloperError('RTC rendering is only available for 3D only scenes.');
1324+
}
1325+
12731326
if (this._state === PrimitiveState.FAILED) {
12741327
return;
12751328
}

Specs/Scene/PrimitiveSpec.js

+91-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
/*global defineSuite*/
22
defineSuite([
33
'Scene/Primitive',
4+
'Core/BoundingSphere',
45
'Core/BoxGeometry',
56
'Core/Cartesian3',
67
'Core/ColorGeometryInstanceAttribute',
78
'Core/ComponentDatatype',
9+
'Core/defined',
810
'Core/Ellipsoid',
911
'Core/Geometry',
1012
'Core/GeometryAttribute',
@@ -18,6 +20,7 @@ defineSuite([
1820
'Core/RuntimeError',
1921
'Core/ShowGeometryInstanceAttribute',
2022
'Core/Transforms',
23+
'Scene/Camera',
2124
'Scene/MaterialAppearance',
2225
'Scene/OrthographicFrustum',
2326
'Scene/PerInstanceColorAppearance',
@@ -28,10 +31,12 @@ defineSuite([
2831
'Specs/pollToPromise'
2932
], function(
3033
Primitive,
34+
BoundingSphere,
3135
BoxGeometry,
3236
Cartesian3,
3337
ColorGeometryInstanceAttribute,
3438
ComponentDatatype,
39+
defined,
3540
Ellipsoid,
3641
Geometry,
3742
GeometryAttribute,
@@ -45,6 +50,7 @@ defineSuite([
4550
RuntimeError,
4651
ShowGeometryInstanceAttribute,
4752
Transforms,
53+
Camera,
4854
MaterialAppearance,
4955
OrthographicFrustum,
5056
PerInstanceColorAppearance,
@@ -319,8 +325,9 @@ defineSuite([
319325

320326
function verifyPrimitiveRender(primitive, rectangle) {
321327
scene.primitives.removeAll();
322-
scene.camera.viewRectangle(rectangle);
323-
328+
if (defined(rectangle)){
329+
scene.camera.viewRectangle(rectangle);
330+
}
324331
expect(scene.renderForSpecs()).toEqual([0, 0, 0, 255]);
325332

326333
scene.primitives.add(primitive);
@@ -352,6 +359,87 @@ defineSuite([
352359
verifyPrimitiveRender(primitive, rectangle2);
353360
});
354361

362+
it('renders RTC', function() {
363+
var dimensions = new Cartesian3(400.0, 300.0, 500.0);
364+
var positionOnEllipsoid = Cartesian3.fromDegrees(-105.0, 45.0);
365+
var boxModelMatrix = Matrix4.multiplyByTranslation(
366+
Transforms.eastNorthUpToFixedFrame(positionOnEllipsoid),
367+
new Cartesian3(0.0, 0.0, dimensions.z * 0.5), new Matrix4());
368+
369+
var boxGeometry = BoxGeometry.createGeometry(BoxGeometry.fromDimensions({
370+
vertexFormat : PerInstanceColorAppearance.VERTEX_FORMAT,
371+
dimensions : dimensions
372+
}));
373+
374+
var positions = boxGeometry.attributes.position.values;
375+
var newPositions = new Float32Array(positions.length);
376+
for (var i = 0; i < positions.length; ++i) {
377+
newPositions[i] = positions[i];
378+
}
379+
boxGeometry.attributes.position.values = newPositions;
380+
boxGeometry.attributes.position.componentDatatype = ComponentDatatype.FLOAT;
381+
382+
BoundingSphere.transform(boxGeometry.boundingSphere, boxModelMatrix, boxGeometry.boundingSphere);
383+
384+
var boxGeometryInstance = new GeometryInstance({
385+
geometry : boxGeometry,
386+
attributes : {
387+
color : new ColorGeometryInstanceAttribute(1.0, 0.0, 0.0, 0.5)
388+
}
389+
});
390+
391+
var primitive = new Primitive({
392+
geometryInstances : boxGeometryInstance,
393+
appearance : new PerInstanceColorAppearance({
394+
closed: true
395+
}),
396+
asynchronous : false,
397+
allowPicking : false,
398+
rtcCenter : boxGeometry.boundingSphere.center
399+
});
400+
401+
// create test camera
402+
var camera = scene.camera;
403+
var testCamera = new Camera(scene);
404+
testCamera.viewBoundingSphere(boxGeometry.boundingSphere);
405+
scene._camera = testCamera;
406+
407+
scene.frameState.scene3DOnly = true;
408+
verifyPrimitiveRender(primitive);
409+
410+
scene._camera = camera;
411+
});
412+
413+
it('RTC throws with more than one instance', function() {
414+
expect(function() {
415+
var primitive = new Primitive({
416+
geometryInstances : [rectangleInstance1, rectangleInstance2],
417+
appearance : new PerInstanceColorAppearance({
418+
closed: true
419+
}),
420+
asynchronous : false,
421+
allowPicking : false,
422+
rtcCenter : Cartesian3.ZERO
423+
});
424+
}).toThrowDeveloperError();
425+
});
426+
427+
it('RTC throws if the scene is not 3D only', function() {
428+
var primitive = new Primitive({
429+
geometryInstances : rectangleInstance1,
430+
appearance : new PerInstanceColorAppearance({
431+
closed: true
432+
}),
433+
asynchronous : false,
434+
allowPicking : false,
435+
rtcCenter : Cartesian3.ZERO
436+
});
437+
438+
expect(function() {
439+
verifyPrimitiveRender(primitive);
440+
}).toThrowDeveloperError();
441+
});
442+
355443
it('updates model matrix for one instance in 3D', function() {
356444
primitive = new Primitive({
357445
geometryInstances : rectangleInstance1,
@@ -945,4 +1033,4 @@ defineSuite([
9451033
primitive.destroy();
9461034
expect(primitive.isDestroyed()).toEqual(true);
9471035
});
948-
}, 'WebGL');
1036+
}, 'WebGL');

0 commit comments

Comments
 (0)