diff --git a/src/apps/render-test/state.ts b/src/apps/render-test/state.ts index c786c0ea7f8ba5f8064f97f714cbd5a990145f49..f31133a57082d202a4cc658cc6fb22bd6a95f801 100644 --- a/src/apps/render-test/state.ts +++ b/src/apps/render-test/state.ts @@ -26,7 +26,7 @@ import { StructureRepresentation } from 'mol-geo/representation/structure'; export default class State { viewer: Viewer - pdbId = '1crn' + pdbId = '4cup' initialized = new BehaviorSubject<boolean>(false) loading = new BehaviorSubject<boolean>(false) @@ -52,7 +52,7 @@ export default class State { // structPointRepr.renderObjects.forEach(viewer.add) const structSpacefillRepr = StructureRepresentation(Spacefill) - await Run(structSpacefillRepr.create(struct, { detail: 2 })) + await Run(structSpacefillRepr.create(struct, { detail: 0 })) structSpacefillRepr.renderObjects.forEach(viewer.add) this.loading.next(false) diff --git a/src/mol-geo/representation/structure/index.ts b/src/mol-geo/representation/structure/index.ts index 786be32ee18ad949f915a45caf47e65314f0022c..a0c4309cbdeffc6db1e9c106715f301e315fe64e 100644 --- a/src/mol-geo/representation/structure/index.ts +++ b/src/mol-geo/representation/structure/index.ts @@ -37,20 +37,16 @@ export function StructureRepresentation<Props>(reprCtor: () => UnitsRepresentati const { elements, units } = structure; const uniqueGroups = EquivalenceClasses<number, ElementGroup>( ElementGroup.hashCode, - (a, b) => units[a.id].model.id === units[b.id].model.id && - OrderedSet.areEqual(a.elements, b.elements) + (a, b) => { + console.log(units, a.id, b.id) + return units[a.id].model.id === units[b.id].model.id && OrderedSet.areEqual(a.elements, b.elements) + } ); - // TODO - // const uniqueOperators = EquivalenceClasses<number, ElementGroup>( - // ElementGroup.hashCode, - // (a, b) => units[a.id].model.id === units[b.id].model.id && - // OrderedSet.areEqual(a.elements, b.elements) - // ); for (let i = 0, _i = ElementSet.unitCount(elements); i < _i; i++) { const group = ElementSet.unitGetByIndex(elements, i); uniqueGroups.add(i, group); - // console.log(i, group) + console.log(i, group) } for (let i = 0, _i = uniqueGroups.groups.length; i < _i; i++) { diff --git a/src/mol-geo/representation/structure/spacefill.ts b/src/mol-geo/representation/structure/spacefill.ts index 3e243611a273fc3412888b9f4a02418fc45032ca..4a0c9ab142300f4f26bc78cf45c4b805374336bd 100644 --- a/src/mol-geo/representation/structure/spacefill.ts +++ b/src/mol-geo/representation/structure/spacefill.ts @@ -15,13 +15,25 @@ import { RepresentationProps, UnitsRepresentation } from './index'; import { Task } from 'mol-task' import { MeshBuilder } from '../../shape/mesh-builder'; import { VdwRadius } from 'mol-model/structure/model/properties/atomic'; -import { ElementColor } from '../../color'; +import { ElementColor, hexColorToArray } from '../../color'; +import { ChunkedArray } from 'mol-data/util'; +import { Color } from 'mol-gl/renderable/mesh'; +import { createColorTexture } from 'mol-gl/util'; export const DefaultSpacefillProps = { detail: 0 } export type SpacefillProps = Partial<typeof DefaultSpacefillProps> +// function buildColorBuffer() { +// if (props && props.color) { +// colors = new Float32Array(icosahedron.vertices.length) +// for (let i = 0, il = colors.length; i < il; i += 3) { +// hexColorToArray(props.color, colors, i) +// } +// } +// } + export default function Spacefill(): UnitsRepresentation<SpacefillProps> { const renderObjects: RenderObject[] = [] @@ -44,9 +56,9 @@ export default function Spacefill(): UnitsRepresentation<SpacefillProps> { v[2] = z[e] Mat4.setTranslation(m, v) + meshBuilder.setId(i) meshBuilder.addIcosahedron(m, { radius: VdwRadius(type_symbol.value(e)), - color: ElementColor(type_symbol.value(e)), detail }) @@ -55,22 +67,46 @@ export default function Spacefill(): UnitsRepresentation<SpacefillProps> { } } + const mesh = meshBuilder.getMesh() + console.log(mesh) + const unitsCount = units.length const transformArray = new Float32Array(unitsCount * 16) for (let i = 0; i < unitsCount; i++) { Mat4.toArray(units[i].operator.matrix, transformArray, i * 16) } - // const color = ValueCell.create(createColorTexture(unitsCount)) - // color.ref.value.set([ 0, 0, 255 ]) + console.log({ unitsCount, elementCount }) - const mesh = meshBuilder.getMesh() - console.log(mesh) + let colorType = 'instance' + let color: Color + + if (colorType === 'attribute') { + const colors = new Float32Array(mesh.vertexCount * 3); + if (mesh.offsetBuffer.ref.value) { + const offsets = mesh.offsetBuffer.ref.value + for (let i = 0, il = mesh.offsetCount - 1; i < il; ++i) { + const start = offsets[i] + const end = offsets[i + 1] + const e = OrderedSet.getAt(elementGroup.elements, i) + const hexColor = ElementColor(type_symbol.value(e)) + for (let i = start, il = end; i < il; ++i) { + hexColorToArray(hexColor, colors, i * 3) + } + } + color = { type: 'attribute', value: ValueCell.create(colors) } + } + } else if (colorType === 'instance') { + const colors = createColorTexture(unitsCount) + colors.set([ 0, 0, 255 ]) + + color = { type: 'instance', value: ValueCell.create(colors) } + } const spheres = createRenderObject('mesh', { position: mesh.vertexBuffer, normal: mesh.normalBuffer, - color: { type: 'attribute', value: (mesh as any).colorBuffer }, + color: color!, transform: ValueCell.create(transformArray), elements: mesh.indexBuffer, diff --git a/src/mol-geo/shape/mesh-builder.ts b/src/mol-geo/shape/mesh-builder.ts index 68e8291259588723fc2a3977f4358c3a7a20ee05..6326ce22f6244f1b035a5e8de610975e1af70b96 100644 --- a/src/mol-geo/shape/mesh-builder.ts +++ b/src/mol-geo/shape/mesh-builder.ts @@ -12,15 +12,13 @@ import Box, { BoxProps } from '../primitive/box'; import Cylinder, { CylinderProps } from '../primitive/cylinder'; import Icosahedron, { IcosahedronProps } from '../primitive/icosahedron'; import { Mesh } from './mesh'; -import { hexColorToArray } from '../color'; - -type ElementProps = { id?: number, color?: number } export interface MeshBuilder { add(t: Mat4, _vertices: Float32Array, _normals: Float32Array, _indices?: Uint32Array): number - addBox(t: Mat4, props?: BoxProps & ElementProps): number - addCylinder(t: Mat4, props?: CylinderProps & ElementProps): number - addIcosahedron(t: Mat4, props?: IcosahedronProps & ElementProps): number + addBox(t: Mat4, props?: BoxProps): number + addCylinder(t: Mat4, props?: CylinderProps): number + addIcosahedron(t: Mat4, props?: IcosahedronProps): number + setId(id: number): void getMesh(): Mesh } @@ -32,15 +30,14 @@ export namespace MeshBuilder { export function create(initialCount = 2048, chunkSize = 1024): MeshBuilder { const vertices = ChunkedArray.create(Float32Array, 3, chunkSize, initialCount); const normals = ChunkedArray.create(Float32Array, 3, chunkSize, initialCount); - const colors = ChunkedArray.create(Float32Array, 3, chunkSize, initialCount); const indices = ChunkedArray.create(Uint32Array, 3, chunkSize * 3, initialCount * 3); - // const offsets = ChunkedArray.create<number>(n => new Uint32Array(n), 1, 1000); - // const elementIds = ChunkedArray.create(Uint32Array, 1, chunkSize, initialCount); + const ids = ChunkedArray.create(Uint32Array, 1, chunkSize, initialCount); + const offsets = ChunkedArray.create(Uint32Array, 1, chunkSize, initialCount); - ChunkedArray.compact(indices, true) + let currentId = -1 - const add = (t: Mat4, _vertices: Float32Array, _normals: Float32Array, _indices: Uint32Array, _colors?: Float32Array) => { + const add = (t: Mat4, _vertices: Float32Array, _normals: Float32Array, _indices: Uint32Array) => { const { elementCount, elementSize } = vertices for (let i = 0, il = _vertices.length; i < il; i += 3) { // position @@ -52,10 +49,7 @@ export namespace MeshBuilder { // Vec3.transformDirection(tmpV, tmpV, n) // TODO ChunkedArray.add3(normals, tmpV[0], tmpV[1], tmpV[2]); - if (_colors) { - Vec3.fromArray(tmpV, _colors, i) - ChunkedArray.add3(colors, tmpV[0], tmpV[1], tmpV[2]); - } + ChunkedArray.add(ids, currentId); } for (let i = 0, il = _indices.length; i < il; i += 3) { ChunkedArray.add3(indices, _indices[i] + elementCount, _indices[i + 1] + elementCount, _indices[i + 2] + elementCount); @@ -65,38 +59,37 @@ export namespace MeshBuilder { return { add, - addBox: (t: Mat4, props?: BoxProps & ElementProps) => { + addBox: (t: Mat4, props?: BoxProps) => { const box = Box(props) return add(t, box.vertices, box.normals, box.indices) }, - addCylinder: (t: Mat4, props?: CylinderProps & ElementProps) => { + addCylinder: (t: Mat4, props?: CylinderProps) => { const cylinder = Cylinder(props) return add(t, cylinder.vertices, cylinder.normals, cylinder.indices) }, - addIcosahedron: (t: Mat4, props?: IcosahedronProps & ElementProps) => { + addIcosahedron: (t: Mat4, props?: IcosahedronProps) => { const icosahedron = Icosahedron(props) - let colors: Float32Array | undefined - if (props && props.color) { - colors = new Float32Array(icosahedron.vertices.length) - for (let i = 0, il = colors.length; i < il; i += 3) { - hexColorToArray(props.color, colors, i) - } + return add(t, icosahedron.vertices, icosahedron.normals, icosahedron.indices) + }, + setId: (id: number) => { + if (currentId !== id) { + currentId = id + ChunkedArray.add(offsets, vertices.elementCount) } - return add(t, icosahedron.vertices, icosahedron.normals, icosahedron.indices, colors) }, getMesh: () => { + ChunkedArray.add(offsets, vertices.elementCount) const mesh = { vertexCount: vertices.elementCount, triangleCount: indices.elementCount, + offsetCount: offsets.elementCount, vertexBuffer: ValueCell.create(ChunkedArray.compact(vertices, true) as Float32Array), indexBuffer: ValueCell.create(ChunkedArray.compact(indices, true) as Uint32Array), normalBuffer: ValueCell.create(ChunkedArray.compact(normals, true) as Float32Array), - colorBuffer: ValueCell.create(ChunkedArray.compact(colors, true) as Float32Array), + idBuffer: ValueCell.create(ChunkedArray.compact(ids, true) as Uint32Array), + offsetBuffer: ValueCell.create(ChunkedArray.compact(offsets, true) as Uint32Array), normalsComputed: true, } - if (colors.elementCount) { - mesh.colorBuffer = ValueCell.create(ChunkedArray.compact(colors, true) as Float32Array) - } return mesh } } diff --git a/src/mol-geo/shape/mesh.ts b/src/mol-geo/shape/mesh.ts index 9f8330766976e3a29d0272349452c513f3b9b089..47671edb3229b10737afff0847045b201f6b8946 100644 --- a/src/mol-geo/shape/mesh.ts +++ b/src/mol-geo/shape/mesh.ts @@ -13,9 +13,12 @@ import { transformPositionArray } from '../util'; export interface Mesh { vertexCount: number, triangleCount: number, + offsetCount: number, vertexBuffer: ValueCell<Float32Array>, indexBuffer: ValueCell<Uint32Array>, normalBuffer: ValueCell<Float32Array | undefined>, + idBuffer: ValueCell<Uint32Array | undefined>, + offsetBuffer: ValueCell<Uint32Array | undefined>, normalsComputed: boolean, vertexAnnotation?: ValueCell<ArrayLike<number>> @@ -26,8 +29,8 @@ export namespace Mesh { export function computeNormalsImmediate(surface: Mesh) { if (surface.normalsComputed) return; - const normals = surface.normalBuffer.ref.value && surface.normalBuffer.ref.value!.length >= surface.vertexCount * 3 - ? surface.normalBuffer.ref.value : new Float32Array(surface.vertexBuffer.ref.value!.length); + const normals = surface.normalBuffer.ref.value && surface.normalBuffer.ref.value.length >= surface.vertexCount * 3 + ? surface.normalBuffer.ref.value : new Float32Array(surface.vertexBuffer.ref.value.length); const v = surface.vertexBuffer.ref.value, triangles = surface.indexBuffer.ref.value; @@ -54,7 +57,7 @@ export namespace Mesh { const f = 1.0 / Math.sqrt(nx * nx + ny * ny + nz * nz); normals[i] *= f; normals[i + 1] *= f; normals[i + 2] *= f; - // console.log([normals[i], normals[i + 1], normals[i + 2]], [v[i], v[i + 1], v[i + 2]]) + // console.log([normals[i], normals[i + 1], normals[i + 2]], [v[i], v[i + 1], v[i + 2]]) } surface.normalBuffer = ValueCell.update(surface.normalBuffer, normals); surface.normalsComputed = true; diff --git a/src/mol-geo/util/marching-cubes/algorithm.ts b/src/mol-geo/util/marching-cubes/algorithm.ts index bf8572a511fc60bb9b4222260eb2f73b0804d24f..015f7f4db104d0fc5a9defef176264e46e62934f 100644 --- a/src/mol-geo/util/marching-cubes/algorithm.ts +++ b/src/mol-geo/util/marching-cubes/algorithm.ts @@ -71,15 +71,20 @@ class MarchingCubesComputation { this.state.vertexBuffer = <any>void 0; this.state.verticesOnEdges = <any>void 0; + const os = this.parameters.oldSurface + let ret: Mesh = { vertexCount: this.state.vertexCount, triangleCount: this.state.triangleCount, - vertexBuffer: this.parameters.oldSurface ? ValueCell.update(this.parameters.oldSurface.vertexBuffer, vb) : ValueCell.create(vb), - indexBuffer: this.parameters.oldSurface ? ValueCell.update(this.parameters.oldSurface.indexBuffer, ib) : ValueCell.create(ib), - normalBuffer: this.parameters.oldSurface ? this.parameters.oldSurface.normalBuffer : ValueCell.create(void 0), + offsetCount: 0, + vertexBuffer: os ? ValueCell.update(os.vertexBuffer, vb) : ValueCell.create(vb), + indexBuffer: os ? ValueCell.update(os.indexBuffer, ib) : ValueCell.create(ib), + normalBuffer: os ? os.normalBuffer : ValueCell.create(void 0), + idBuffer: os ? os.idBuffer : ValueCell.create(void 0), + offsetBuffer: os ? os.offsetBuffer : ValueCell.create(void 0), vertexAnnotation: this.state.annotate - ? this.parameters.oldSurface && this.parameters.oldSurface.vertexAnnotation - ? ValueCell.update(this.parameters.oldSurface.vertexAnnotation, ChunkedArray.compact(this.state.annotationBuffer)) + ? os && os.vertexAnnotation + ? ValueCell.update(os.vertexAnnotation, ChunkedArray.compact(this.state.annotationBuffer)) : ValueCell.create(ChunkedArray.compact(this.state.annotationBuffer)) : void 0, normalsComputed: false diff --git a/src/mol-gl/renderable/mesh.ts b/src/mol-gl/renderable/mesh.ts index 37c81bbef98416c819a72914e14ca060ee8eab68..b9f62d6d16b165731ce38bb1808c2080bf383bac 100644 --- a/src/mol-gl/renderable/mesh.ts +++ b/src/mol-gl/renderable/mesh.ts @@ -20,7 +20,7 @@ type Uniforms = { [k: string]: REGL.Uniform | REGL.Texture } type AttributeColor = { type: 'attribute', value: ValueCell<Float32Array> } type InstanceColor = { type: 'instance', value: ValueCell<ColorTexture> } type ElementColor = { type: 'element', value: ValueCell<ColorTexture> } -type Color = AttributeColor | InstanceColor | ElementColor +export type Color = AttributeColor | InstanceColor | ElementColor namespace Mesh { export type Data = { diff --git a/src/mol-gl/shader/mesh.frag b/src/mol-gl/shader/mesh.frag index caa69f0c8c1f62219f7a5b15de4511152632821c..0f4475b80802b9988ec0cdeb22f525113306b220 100644 --- a/src/mol-gl/shader/mesh.frag +++ b/src/mol-gl/shader/mesh.frag @@ -4,6 +4,9 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ +// #define ATTRIBUTE_COLOR +#define INSTANCE_COLOR + precision highp float; struct Light { @@ -17,7 +20,13 @@ struct Light { uniform Light light; uniform mat4 view; -varying vec3 vNormal, vViewPosition, vColor; +varying vec3 vNormal, vViewPosition; + +#if defined( UNIFORM_COLOR ) + uniform vec3 color; +#elif defined( ATTRIBUTE_COLOR ) || defined( INSTANCE_COLOR ) || defined( ELEMENT_COLOR ) + varying vec3 vColor; +#endif float phongSpecular(vec3 lightDirection, vec3 viewDirection, vec3 surfaceNormal, float shininess) { //Calculate Phong power @@ -50,6 +59,13 @@ const float roughness = 5.0; const float albedo = 0.95; void main() { + // material color + #if defined( UNIFORM_COLOR ) + vec3 material = color; + #elif defined( ATTRIBUTE_COLOR ) || defined( INSTANCE_COLOR ) || defined( ELEMENT_COLOR ) + vec3 material = vColor; + #endif + // determine surface to light direction // vec4 lightPosition = view * vec4(light.position, 1.0); vec4 lightPosition = vec4(vec3(0.0, 0.0, -10000.0), 1.0); @@ -69,10 +85,10 @@ void main() { vec3 ambient = light.ambient; // add the lighting - vec3 color = vColor * (diffuse + ambient) + specular; + vec3 finalColor = material * (diffuse + ambient) + specular; // gl_FragColor.rgb = N; // gl_FragColor.rgb = vec3(1.0, 0.0, 0.0); - gl_FragColor.rgb = color; + gl_FragColor.rgb = finalColor; gl_FragColor.a = 1.0; } \ No newline at end of file diff --git a/src/mol-gl/shader/mesh.vert b/src/mol-gl/shader/mesh.vert index 5f508ecb8e1e05ad7e0b2d0361ee88dd72f78689..1ea5b9ac044c86d002ce06fed2504313ebd63103 100644 --- a/src/mol-gl/shader/mesh.vert +++ b/src/mol-gl/shader/mesh.vert @@ -4,8 +4,8 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -#define ATTRIBUTE_COLOR -// #define INSTANCE_COLOR +// #define ATTRIBUTE_COLOR +#define INSTANCE_COLOR precision highp float; @@ -14,7 +14,9 @@ uniform mat4 projection, model, view; uniform int objectId; uniform int instanceCount; -#if defined( ATTRIBUTE_COLOR ) +#if defined( UNIFORM_COLOR ) + uniform vec3 color; +#elif defined( ATTRIBUTE_COLOR ) attribute vec3 color; #elif defined( INSTANCE_COLOR ) || defined( ELEMENT_COLOR ) uniform vec2 colorTexSize; @@ -42,8 +44,6 @@ void main(){ vColor = read_vec3(colorTex, instanceId, colorTexSize); // #elif defined( ELEMENT_COLOR ) // vColor = read_vec3(colorTex, instanceId * instanceCount + elementId, colorTexSize); - #else - vColor = vec3(0.0, 1.0, 0.0); #endif mat4 transform = mat4(transformColumn0, transformColumn1, transformColumn2, transformColumn3);