diff --git a/src/mol-io/reader/ply/parser.ts b/src/mol-io/reader/ply/parser.ts index bd9ce4f2d044a9e0cf62efe7c5f06c87d4258658..61ea12db46f731cf9aca29dbb253d4c0107707ca 100644 --- a/src/mol-io/reader/ply/parser.ts +++ b/src/mol-io/reader/ply/parser.ts @@ -11,6 +11,9 @@ import { Tokenizer, TokenBuilder, Tokens } from '../common/text/tokenizer'; import { Column } from 'mol-data/db'; import { TokenColumn } from '../common/text/column/token'; +// TODO add support for binary ply files +// TODO parse elements asynchronously + interface State { data: string tokenizer: Tokenizer diff --git a/src/mol-model-formats/shape/ply.ts b/src/mol-model-formats/shape/ply.ts index edeceded4abdafa8e59e8370fef32b4c0b7f9f56..7b3f9bcff93c620bd0a911366ecb1c992f56f1d0 100644 --- a/src/mol-model-formats/shape/ply.ts +++ b/src/mol-model-formats/shape/ply.ts @@ -97,9 +97,8 @@ function createPlyShapeParams(plyFile?: PlyFile) { export const PlyShapeParams = createPlyShapeParams() export type PlyShapeParams = typeof PlyShapeParams -async function getMesh(ctx: RuntimeContext, vertex: PlyTable, face: PlyList, groupIds: ArrayLike<number>, mesh?: Mesh) { - const builderState = MeshBuilder.createState(vertex.rowCount, vertex.rowCount / 4, mesh) - const { vertices, normals, indices, groups } = builderState +function addVerticesRange(begI: number, endI: number, state: MeshBuilder.State, vertex: PlyTable, groupIds: ArrayLike<number>) { + const { vertices, normals, groups } = state const x = vertex.getProperty('x') const y = vertex.getProperty('y') @@ -112,17 +111,17 @@ async function getMesh(ctx: RuntimeContext, vertex: PlyTable, face: PlyList, gro const hasNormals = !!nx && !!ny && !!nz - for (let i = 0, il = vertex.rowCount; i < il; ++i) { - if (i % 100000 === 0 && ctx.shouldUpdate) await ctx.update({ current: i, max: il, message: `adding vertex ${i}` }) - + for (let i = begI; i < endI; ++i) { ChunkedArray.add3(vertices, x.value(i), y.value(i), z.value(i)) if (hasNormals) ChunkedArray.add3(normals, nx!.value(i), ny!.value(i), nz!.value(i)); ChunkedArray.add(groups, groupIds[i]) } +} - for (let i = 0, il = face.rowCount; i < il; ++i) { - if (i % 100000 === 0 && ctx.shouldUpdate) await ctx.update({ current: i, max: il, message: `adding face ${i}` }) +function addFacesRange(begI: number, endI: number, state: MeshBuilder.State, face: PlyList) { + const { indices } = state + for (let i = begI; i < endI; ++i) { const { entries, count } = face.value(i) if (count === 3) { // triangle @@ -133,6 +132,38 @@ async function getMesh(ctx: RuntimeContext, vertex: PlyTable, face: PlyList, gro ChunkedArray.add3(indices, entries[2], entries[0], entries[3]) } } +} + +async function getMesh(ctx: RuntimeContext, vertex: PlyTable, face: PlyList, groupIds: ArrayLike<number>, mesh?: Mesh) { + const builderState = MeshBuilder.createState(vertex.rowCount, vertex.rowCount / 4, mesh) + + const x = vertex.getProperty('x') + const y = vertex.getProperty('y') + const z = vertex.getProperty('z') + if (!x || !y || !z) throw new Error('missing coordinate properties') + + const nx = vertex.getProperty('nx') + const ny = vertex.getProperty('ny') + const nz = vertex.getProperty('nz') + + const hasNormals = !!nx && !!ny && !!nz + const updateChunk = 100000 + + for (let i = 0, il = vertex.rowCount; i < il; i += updateChunk) { + addVerticesRange(i, Math.min(i + updateChunk, il), builderState, vertex, groupIds) + + if (ctx.shouldUpdate) { + await ctx.update({ message: 'adding ply mesh vertices', current: i, max: il }) + } + } + + for (let i = 0, il = face.rowCount; i < il; i += updateChunk) { + addFacesRange(i, Math.min(i + updateChunk, il), builderState, face) + + if (ctx.shouldUpdate) { + await ctx.update({ message: 'adding ply mesh faces', current: i, max: il }) + } + } const m = MeshBuilder.getMesh(builderState); m.normalsComputed = hasNormals