Alexander Rose 7 years ago
parent
commit
b8a4365dbe

+ 2 - 2
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)

+ 5 - 9
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++) {

+ 43 - 7
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,
 

+ 22 - 29
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
             }
         }

+ 6 - 3
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;

+ 10 - 5
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

+ 1 - 1
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 = {

+ 19 - 3
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;
 }

+ 5 - 5
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);