molstar
Version:
A comprehensive macromolecular library.
221 lines • 8.66 kB
JavaScript
/**
* Copyright (c) 2018-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
* @author David Sehnal <david.sehnal@gmail.com>
*/
import { createRenderable } from './render-object';
import { Object3D } from './object3d';
import { Sphere3D } from '../mol-math/geometry';
import { CommitQueue } from './commit-queue';
import { now } from '../mol-util/now';
import { arraySetRemove } from '../mol-util/array';
import { BoundaryHelper } from '../mol-math/geometry/boundary-helper';
import { hash1 } from '../mol-data/util';
var boundaryHelper = new BoundaryHelper('98');
function calculateBoundingSphere(renderables, boundingSphere, onlyVisible) {
boundaryHelper.reset();
for (var i = 0, il = renderables.length; i < il; ++i) {
if (onlyVisible && !renderables[i].state.visible)
continue;
var boundingSphere_1 = renderables[i].values.boundingSphere.ref.value;
if (!boundingSphere_1.radius)
continue;
boundaryHelper.includeSphere(boundingSphere_1);
}
boundaryHelper.finishedIncludeStep();
for (var i = 0, il = renderables.length; i < il; ++i) {
if (onlyVisible && !renderables[i].state.visible)
continue;
var boundingSphere_2 = renderables[i].values.boundingSphere.ref.value;
if (!boundingSphere_2.radius)
continue;
boundaryHelper.radiusSphere(boundingSphere_2);
}
return boundaryHelper.getSphere(boundingSphere);
}
function renderableSort(a, b) {
var drawProgramIdA = a.getProgram('colorBlended').id;
var drawProgramIdB = b.getProgram('colorBlended').id;
var materialIdA = a.materialId;
var materialIdB = b.materialId;
if (drawProgramIdA !== drawProgramIdB) {
// sort by program id to minimize gl state changes
return drawProgramIdA - drawProgramIdB;
}
else if (materialIdA !== materialIdB) {
// sort by material id to minimize gl state changes
return materialIdA - materialIdB;
}
else {
return a.id - b.id;
}
}
var Scene;
(function (Scene) {
function create(ctx) {
var renderableMap = new Map();
var renderables = [];
var boundingSphere = Sphere3D();
var boundingSphereVisible = Sphere3D();
var primitives = [];
var volumes = [];
var boundingSphereDirty = true;
var boundingSphereVisibleDirty = true;
var object3d = Object3D.create();
var view = object3d.view, position = object3d.position, direction = object3d.direction, up = object3d.up;
function add(o) {
if (!renderableMap.has(o)) {
var renderable = createRenderable(ctx, o);
renderables.push(renderable);
if (o.type === 'direct-volume') {
volumes.push(renderable);
}
else {
primitives.push(renderable);
}
renderableMap.set(o, renderable);
boundingSphereDirty = true;
boundingSphereVisibleDirty = true;
return renderable;
}
else {
console.warn("RenderObject with id '" + o.id + "' already present");
return renderableMap.get(o);
}
}
function remove(o) {
var renderable = renderableMap.get(o);
if (renderable) {
renderable.dispose();
arraySetRemove(renderables, renderable);
arraySetRemove(primitives, renderable);
arraySetRemove(volumes, renderable);
renderableMap.delete(o);
boundingSphereDirty = true;
boundingSphereVisibleDirty = true;
}
}
var commitBulkSize = 100;
function commit(maxTimeMs) {
var start = now();
var i = 0;
while (true) {
var o = commitQueue.tryGetRemove();
if (!o)
break;
remove(o);
if (++i % commitBulkSize === 0 && now() - start > maxTimeMs)
return false;
}
while (true) {
var o = commitQueue.tryGetAdd();
if (!o)
break;
add(o);
if (++i % commitBulkSize === 0 && now() - start > maxTimeMs)
return false;
}
renderables.sort(renderableSort);
return true;
}
var commitQueue = new CommitQueue();
var visibleHash = -1;
function computeVisibleHash() {
var hash = 23;
for (var i = 0, il = renderables.length; i < il; ++i) {
if (!renderables[i].state.visible)
continue;
hash = (31 * hash + renderables[i].id) | 0;
}
hash = hash1(hash);
if (hash === -1)
hash = 0;
return hash;
}
function syncVisibility() {
var newVisibleHash = computeVisibleHash();
if (newVisibleHash !== visibleHash) {
boundingSphereVisibleDirty = true;
return true;
}
else {
return false;
}
}
return {
view: view,
position: position,
direction: direction,
up: up,
renderables: renderables,
primitives: { view: view, position: position, direction: direction, up: up, renderables: primitives },
volumes: { view: view, position: position, direction: direction, up: up, renderables: volumes },
syncVisibility: syncVisibility,
update: function (objects, keepBoundingSphere) {
var _a;
Object3D.update(object3d);
if (objects) {
for (var i = 0, il = objects.length; i < il; ++i) {
(_a = renderableMap.get(objects[i])) === null || _a === void 0 ? void 0 : _a.update();
}
}
else {
for (var i = 0, il = renderables.length; i < il; ++i) {
renderables[i].update();
}
}
if (!keepBoundingSphere) {
boundingSphereDirty = true;
boundingSphereVisibleDirty = true;
}
else {
syncVisibility();
}
},
add: function (o) { return commitQueue.add(o); },
remove: function (o) { return commitQueue.remove(o); },
commit: function (maxTime) {
if (maxTime === void 0) { maxTime = Number.MAX_VALUE; }
return commit(maxTime);
},
get needsCommit() { return !commitQueue.isEmpty; },
has: function (o) {
return renderableMap.has(o);
},
clear: function () {
for (var i = 0, il = renderables.length; i < il; ++i) {
renderables[i].dispose();
}
renderables.length = 0;
renderableMap.clear();
boundingSphereDirty = true;
boundingSphereVisibleDirty = true;
},
forEach: function (callbackFn) {
renderableMap.forEach(callbackFn);
},
get count() {
return renderables.length;
},
get boundingSphere() {
if (boundingSphereDirty) {
calculateBoundingSphere(renderables, boundingSphere, false);
boundingSphereDirty = false;
}
return boundingSphere;
},
get boundingSphereVisible() {
if (boundingSphereVisibleDirty) {
calculateBoundingSphere(renderables, boundingSphereVisible, true);
boundingSphereVisibleDirty = false;
visibleHash = computeVisibleHash();
}
return boundingSphereVisible;
}
};
}
Scene.create = create;
})(Scene || (Scene = {}));
export { Scene };
//# sourceMappingURL=scene.js.map