mirror of
https://github.com/molstar/molstar.git
synced 2026-06-04 13:30:24 +08:00
add line-strips to lines geo
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2018-2025 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2018-2026 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
@@ -85,7 +85,7 @@ export namespace Geometry {
|
||||
case 'spheres': return geometry.sphereCount * 6;
|
||||
case 'cylinders': return geometry.cylinderCount * 6;
|
||||
case 'text': return geometry.charCount * 4;
|
||||
case 'lines': return geometry.lineCount * 4;
|
||||
case 'lines': return geometry.vertexCount;
|
||||
case 'direct-volume':
|
||||
const [x, y, z] = geometry.gridDimension.ref.value;
|
||||
return x * y * z;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2018-2023 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2018-2026 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
* @author Gianluca Tomasello <giagitom@gmail.com>
|
||||
@@ -10,6 +10,15 @@ import { Lines } from './lines';
|
||||
import { Mat4, Vec3 } from '../../../mol-math/linear-algebra';
|
||||
import { Cage } from '../../primitive/cage';
|
||||
|
||||
// avoiding namespace lookup improved performance in Chrome (Aug 2020)
|
||||
const caAdd = ChunkedArray.add;
|
||||
const caAdd2 = ChunkedArray.add2;
|
||||
const caAdd3 = ChunkedArray.add3;
|
||||
|
||||
const tmpVecA = Vec3();
|
||||
const tmpVecB = Vec3();
|
||||
const tmpDir = Vec3();
|
||||
|
||||
export interface LinesBuilder {
|
||||
add(startX: number, startY: number, startZ: number, endX: number, endY: number, endZ: number, group: number): void
|
||||
addVec(start: Vec3, end: Vec3, group: number): void
|
||||
@@ -19,14 +28,6 @@ export interface LinesBuilder {
|
||||
getLines(): Lines
|
||||
}
|
||||
|
||||
const tmpVecA = Vec3();
|
||||
const tmpVecB = Vec3();
|
||||
const tmpDir = Vec3();
|
||||
|
||||
// avoiding namespace lookup improved performance in Chrome (Aug 2020)
|
||||
const caAdd = ChunkedArray.add;
|
||||
const caAdd3 = ChunkedArray.add3;
|
||||
|
||||
export namespace LinesBuilder {
|
||||
export function create(initialCount = 2048, chunkSize = 1024, lines?: Lines): LinesBuilder {
|
||||
const groups = ChunkedArray.create(Float32Array, 1, chunkSize, lines ? lines.groupBuffer.ref.value : initialCount);
|
||||
@@ -89,13 +90,15 @@ export namespace LinesBuilder {
|
||||
},
|
||||
getLines: () => {
|
||||
const lineCount = groups.elementCount / 4;
|
||||
const vertexCount = groups.elementCount;
|
||||
const gb = ChunkedArray.compact(groups, true) as Float32Array;
|
||||
const sb = ChunkedArray.compact(starts, true) as Float32Array;
|
||||
const eb = ChunkedArray.compact(ends, true) as Float32Array;
|
||||
const mb = lines && lineCount <= lines.lineCount ? lines.mappingBuffer.ref.value : new Float32Array(lineCount * 8);
|
||||
const ib = lines && lineCount <= lines.lineCount ? lines.indexBuffer.ref.value : new Uint32Array(lineCount * 6);
|
||||
if (!lines || lineCount > lines.lineCount) fillMappingAndIndices(lineCount, mb, ib);
|
||||
return Lines.create(mb, ib, gb, sb, eb, lineCount, lines);
|
||||
const mb = lines && lineCount <= lines.lineCount && lines.stripCount.ref.value === 0 ? lines.mappingBuffer.ref.value : new Float32Array(lineCount * 8);
|
||||
const ib = lines && lineCount <= lines.lineCount && lines.stripCount.ref.value === 0 ? lines.indexBuffer.ref.value : new Uint32Array(lineCount * 6);
|
||||
const ob = lines ? lines.stripBuffer.ref.value : new Uint32Array(0);
|
||||
if (!lines || lineCount > lines.lineCount || lines.stripCount.ref.value > 0) fillMappingAndIndices(lineCount, mb, ib);
|
||||
return Lines.create(mb, ib, gb, sb, eb, ob, lineCount, vertexCount, 0, lines);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -117,3 +120,104 @@ function fillMappingAndIndices(n: number, mb: Float32Array, ib: Uint32Array) {
|
||||
ib[io + 3] = o + 1; ib[io + 4] = o + 3; ib[io + 5] = o + 2;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
export interface StripLinesBuilder {
|
||||
start(group: number): void
|
||||
add(x: number, y: number, z: number): void
|
||||
addVec(v: Vec3): void
|
||||
end(): void
|
||||
getLines(): Lines
|
||||
}
|
||||
|
||||
export namespace StripLinesBuilder {
|
||||
export function create(initialCount = 2048, chunkSize = 1024, lines?: Lines): StripLinesBuilder {
|
||||
const groups = ChunkedArray.create(Float32Array, 1, chunkSize, lines ? lines.groupBuffer.ref.value : initialCount);
|
||||
const starts = ChunkedArray.create(Float32Array, 3, chunkSize, lines ? lines.startBuffer.ref.value : initialCount);
|
||||
const ends = ChunkedArray.create(Float32Array, 3, chunkSize, lines ? lines.endBuffer.ref.value : initialCount);
|
||||
const mapping = ChunkedArray.create(Float32Array, 2, chunkSize, lines ? lines.mappingBuffer.ref.value : initialCount);
|
||||
const indices = ChunkedArray.create(Uint32Array, 3, chunkSize, lines ? lines.indexBuffer.ref.value : initialCount);
|
||||
const strips = ChunkedArray.create(Uint32Array, 1, chunkSize, lines ? lines.stripBuffer.ref.value : initialCount);
|
||||
|
||||
let stripGroup = 0;
|
||||
let pointCount = 0;
|
||||
let firstVertexOffset = 0;
|
||||
let prevX = 0, prevY = 0, prevZ = 0;
|
||||
|
||||
const addPoint = (x: number, y: number, z: number) => {
|
||||
if (pointCount === 0) {
|
||||
firstVertexOffset = groups.elementCount;
|
||||
prevX = x; prevY = y; prevZ = z;
|
||||
pointCount = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
const vertexOffset = groups.elementCount;
|
||||
|
||||
if (pointCount === 1) {
|
||||
caAdd3(starts, prevX, prevY, prevZ);
|
||||
caAdd3(ends, x, y, z);
|
||||
caAdd(groups, stripGroup);
|
||||
caAdd2(mapping, -1, -1); // left, start
|
||||
|
||||
caAdd3(starts, prevX, prevY, prevZ);
|
||||
caAdd3(ends, x, y, z);
|
||||
caAdd(groups, stripGroup);
|
||||
caAdd2(mapping, 1, -1); // right, start
|
||||
}
|
||||
|
||||
caAdd3(starts, prevX, prevY, prevZ);
|
||||
caAdd3(ends, x, y, z);
|
||||
caAdd(groups, stripGroup);
|
||||
caAdd2(mapping, -1, 1); // left, end
|
||||
|
||||
caAdd3(starts, prevX, prevY, prevZ);
|
||||
caAdd3(ends, x, y, z);
|
||||
caAdd(groups, stripGroup);
|
||||
caAdd2(mapping, 1, 1); // right, end
|
||||
|
||||
const prevOffset = pointCount === 1 ? firstVertexOffset : vertexOffset - 2;
|
||||
const currOffset = pointCount === 1 ? vertexOffset + 2 : vertexOffset;
|
||||
// Triangle 1: prev-left, prev-right, curr-left
|
||||
caAdd3(indices, prevOffset, prevOffset + 1, currOffset);
|
||||
// Triangle 2: prev-right, curr-right, curr-left
|
||||
caAdd3(indices, prevOffset + 1, currOffset + 1, currOffset);
|
||||
|
||||
prevX = x; prevY = y; prevZ = z;
|
||||
pointCount++;
|
||||
};
|
||||
|
||||
return {
|
||||
start: (group: number) => {
|
||||
stripGroup = group;
|
||||
pointCount = 0;
|
||||
if (strips.elementCount === 0) {
|
||||
caAdd(strips, 0);
|
||||
}
|
||||
},
|
||||
add: (x: number, y: number, z: number) => {
|
||||
addPoint(x, y, z);
|
||||
},
|
||||
addVec: (v: Vec3) => {
|
||||
addPoint(v[0], v[1], v[2]);
|
||||
},
|
||||
end: () => {
|
||||
pointCount = 0;
|
||||
caAdd(strips, groups.elementCount);
|
||||
},
|
||||
getLines: () => {
|
||||
const lineCount = indices.elementCount / 2;
|
||||
const vertexCount = groups.elementCount;
|
||||
const stripCount = strips.elementCount - 1;
|
||||
const gb = ChunkedArray.compact(groups, true) as Float32Array;
|
||||
const sb = ChunkedArray.compact(starts, true) as Float32Array;
|
||||
const eb = ChunkedArray.compact(ends, true) as Float32Array;
|
||||
const mb = ChunkedArray.compact(mapping, true) as Float32Array;
|
||||
const ib = ChunkedArray.compact(indices, true) as Uint32Array;
|
||||
const ob = ChunkedArray.compact(strips, true) as Uint32Array;
|
||||
return Lines.create(mb, ib, gb, sb, eb, ob, lineCount, vertexCount, stripCount, lines);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,8 @@ export interface Lines {
|
||||
|
||||
/** Number of lines */
|
||||
lineCount: number,
|
||||
/** Number of vertices */
|
||||
vertexCount: number,
|
||||
|
||||
/** Mapping buffer as array of xy values wrapped in a value cell */
|
||||
readonly mappingBuffer: ValueCell<Float32Array>,
|
||||
@@ -47,6 +49,11 @@ export interface Lines {
|
||||
/** Line end buffer as array of xyz values wrapped in a value cell */
|
||||
readonly endBuffer: ValueCell<Float32Array>,
|
||||
|
||||
/** Number of strips wrapped in a value cell */
|
||||
readonly stripCount: ValueCell<number>,
|
||||
/** Strip buffer as array of vertex offsets wrapped in a value cell */
|
||||
readonly stripBuffer: ValueCell<Uint32Array>,
|
||||
|
||||
/** Bounding sphere of the lines */
|
||||
readonly boundingSphere: Sphere3D
|
||||
/** Maps group ids to line indices */
|
||||
@@ -57,10 +64,10 @@ export interface Lines {
|
||||
}
|
||||
|
||||
export namespace Lines {
|
||||
export function create(mappings: Float32Array, indices: Uint32Array, groups: Float32Array, starts: Float32Array, ends: Float32Array, lineCount: number, lines?: Lines): Lines {
|
||||
export function create(mappings: Float32Array, indices: Uint32Array, groups: Float32Array, starts: Float32Array, ends: Float32Array, strips: Uint32Array, lineCount: number, vertexCount: number, stripCount: number, lines?: Lines): Lines {
|
||||
return lines ?
|
||||
update(mappings, indices, groups, starts, ends, lineCount, lines) :
|
||||
fromArrays(mappings, indices, groups, starts, ends, lineCount);
|
||||
update(mappings, indices, groups, starts, ends, strips, lineCount, vertexCount, stripCount, lines) :
|
||||
fromArrays(mappings, indices, groups, starts, ends, strips, lineCount, vertexCount, stripCount);
|
||||
}
|
||||
|
||||
export function createEmpty(lines?: Lines): Lines {
|
||||
@@ -69,7 +76,8 @@ export namespace Lines {
|
||||
const gb = lines ? lines.groupBuffer.ref.value : new Float32Array(0);
|
||||
const sb = lines ? lines.startBuffer.ref.value : new Float32Array(0);
|
||||
const eb = lines ? lines.endBuffer.ref.value : new Float32Array(0);
|
||||
return create(mb, ib, gb, sb, eb, 0, lines);
|
||||
const ob = lines ? lines.stripBuffer.ref.value : new Uint32Array(0);
|
||||
return create(mb, ib, gb, sb, eb, ob, 0, 0, 0, lines);
|
||||
}
|
||||
|
||||
export function fromMesh(mesh: Mesh, lines?: Lines) {
|
||||
@@ -95,12 +103,14 @@ export namespace Lines {
|
||||
|
||||
function hashCode(lines: Lines) {
|
||||
return hashFnv32a([
|
||||
lines.lineCount, lines.mappingBuffer.ref.version, lines.indexBuffer.ref.version,
|
||||
lines.groupBuffer.ref.version, lines.startBuffer.ref.version, lines.endBuffer.ref.version
|
||||
lines.lineCount, lines.vertexCount,
|
||||
lines.mappingBuffer.ref.version, lines.indexBuffer.ref.version,
|
||||
lines.groupBuffer.ref.version, lines.startBuffer.ref.version, lines.endBuffer.ref.version,
|
||||
lines.stripCount.ref.version, lines.stripBuffer.ref.version
|
||||
]);
|
||||
}
|
||||
|
||||
function fromArrays(mappings: Float32Array, indices: Uint32Array, groups: Float32Array, starts: Float32Array, ends: Float32Array, lineCount: number): Lines {
|
||||
function fromArrays(mappings: Float32Array, indices: Uint32Array, groups: Float32Array, starts: Float32Array, ends: Float32Array, strips: Uint32Array, lineCount: number, vertexCount: number, stripCount: number): Lines {
|
||||
|
||||
const boundingSphere = Sphere3D();
|
||||
let groupMapping: GroupMapping;
|
||||
@@ -111,11 +121,14 @@ export namespace Lines {
|
||||
const lines = {
|
||||
kind: 'lines' as const,
|
||||
lineCount,
|
||||
vertexCount,
|
||||
mappingBuffer: ValueCell.create(mappings),
|
||||
indexBuffer: ValueCell.create(indices),
|
||||
groupBuffer: ValueCell.create(groups),
|
||||
startBuffer: ValueCell.create(starts),
|
||||
endBuffer: ValueCell.create(ends),
|
||||
stripCount: ValueCell.create(stripCount),
|
||||
stripBuffer: ValueCell.create(strips),
|
||||
get boundingSphere() {
|
||||
const newHash = hashCode(lines);
|
||||
if (newHash !== currentHash) {
|
||||
@@ -145,24 +158,27 @@ export namespace Lines {
|
||||
return lines;
|
||||
}
|
||||
|
||||
function update(mappings: Float32Array, indices: Uint32Array, groups: Float32Array, starts: Float32Array, ends: Float32Array, lineCount: number, lines: Lines) {
|
||||
if (lineCount > lines.lineCount) {
|
||||
function update(mappings: Float32Array, indices: Uint32Array, groups: Float32Array, starts: Float32Array, ends: Float32Array, strips: Uint32Array, lineCount: number, vertexCount: number, stripCount: number, lines: Lines) {
|
||||
if (lineCount > lines.lineCount || stripCount !== lines.stripCount.ref.value || stripCount > 0) {
|
||||
ValueCell.update(lines.mappingBuffer, mappings);
|
||||
ValueCell.update(lines.indexBuffer, indices);
|
||||
}
|
||||
lines.lineCount = lineCount;
|
||||
lines.vertexCount = vertexCount;
|
||||
ValueCell.update(lines.groupBuffer, groups);
|
||||
ValueCell.update(lines.startBuffer, starts);
|
||||
ValueCell.update(lines.endBuffer, ends);
|
||||
ValueCell.updateIfChanged(lines.stripCount, stripCount);
|
||||
ValueCell.update(lines.stripBuffer, strips);
|
||||
return lines;
|
||||
}
|
||||
|
||||
export function transform(lines: Lines, t: Mat4) {
|
||||
const start = lines.startBuffer.ref.value;
|
||||
transformPositionArray(t, start, 0, lines.lineCount * 4);
|
||||
transformPositionArray(t, start, 0, lines.vertexCount);
|
||||
ValueCell.update(lines.startBuffer, start);
|
||||
const end = lines.endBuffer.ref.value;
|
||||
transformPositionArray(t, end, 0, lines.lineCount * 4);
|
||||
transformPositionArray(t, end, 0, lines.vertexCount);
|
||||
ValueCell.update(lines.endBuffer, end);
|
||||
}
|
||||
|
||||
@@ -222,7 +238,7 @@ export namespace Lines {
|
||||
const material = createEmptySubstance();
|
||||
const clipping = createEmptyClipping();
|
||||
|
||||
const counts = { drawCount: lines.lineCount * 2 * 3, vertexCount: lines.lineCount * 4, groupCount, instanceCount };
|
||||
const counts = { drawCount: lines.lineCount * 2 * 3, vertexCount: lines.vertexCount, groupCount, instanceCount };
|
||||
|
||||
const invariantBoundingSphere = Sphere3D.clone(lines.boundingSphere);
|
||||
const boundingSphere = calculateTransformBoundingSphere(invariantBoundingSphere, transform.aTransform.ref.value, instanceCount, 0);
|
||||
@@ -253,6 +269,9 @@ export namespace Lines {
|
||||
dLineSizeAttenuation: ValueCell.create(props.lineSizeAttenuation),
|
||||
uDoubleSided: ValueCell.create(true),
|
||||
dFlipSided: ValueCell.create(false),
|
||||
|
||||
stripCount: lines.stripCount,
|
||||
stripOffsets: lines.stripBuffer,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2018-2025 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2018-2026 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
@@ -7,7 +7,7 @@
|
||||
import { Renderable, RenderableState, createRenderable } from '../renderable';
|
||||
import { WebGLContext } from '../webgl/context';
|
||||
import { createGraphicsRenderItem, Transparency } from '../webgl/render-item';
|
||||
import { GlobalUniformSchema, BaseSchema, AttributeSpec, DefineSpec, Values, InternalSchema, SizeSchema, ElementsSpec, InternalValues, GlobalTextureSchema, UniformSpec, GlobalDefineValues, GlobalDefines, GlobalDefineSchema } from './schema';
|
||||
import { GlobalUniformSchema, BaseSchema, AttributeSpec, DefineSpec, Values, InternalSchema, SizeSchema, ElementsSpec, InternalValues, GlobalTextureSchema, UniformSpec, GlobalDefineValues, GlobalDefines, GlobalDefineSchema, ValueSpec } from './schema';
|
||||
import { ValueCell } from '../../mol-util';
|
||||
import { LinesShaderCode } from '../shader-code';
|
||||
|
||||
@@ -22,6 +22,8 @@ export const LinesSchema = {
|
||||
dLineSizeAttenuation: DefineSpec('boolean'),
|
||||
uDoubleSided: UniformSpec('b', 'material'),
|
||||
dFlipSided: DefineSpec('boolean'),
|
||||
stripCount: ValueSpec('number'),
|
||||
stripOffsets: ValueSpec('uint32'),
|
||||
};
|
||||
export type LinesSchema = typeof LinesSchema
|
||||
export type LinesValues = Values<LinesSchema>
|
||||
|
||||
Reference in New Issue
Block a user