Alexander Rose 7 лет назад
Родитель
Сommit
3c428616ec

+ 55 - 9
src/apps/render-test/state.ts

@@ -15,18 +15,41 @@ import { createTransformAttributes } from 'mol-gl/renderable/util';
 import { calculateTextureInfo } from 'mol-gl/util';
 import { calculateTextureInfo } from 'mol-gl/util';
 import Icosahedron from 'mol-geo/primitive/icosahedron'
 import Icosahedron from 'mol-geo/primitive/icosahedron'
 import Box from 'mol-geo/primitive/box'
 import Box from 'mol-geo/primitive/box'
+import Spacefill from 'mol-geo/representation/structure/spacefill'
+
+import CIF from 'mol-io/reader/cif'
+import Computation from 'mol-util/computation'
+import { AtomSet, Structure } from 'mol-model/structure'
+import { UnitRepresentation } from 'mol-geo/representation/structure';
+
+async function parseCif(data: string|Uint8Array) {
+    const comp = CIF.parse(data)
+    const ctx = Computation.observable({
+        updateRateMs: 250
+    })
+    const parsed = await comp(ctx);
+    if (parsed.isError) throw parsed;
+    return parsed
+}
+
+async function getPdb(pdb: string) {
+    const data = await fetch(`https://files.rcsb.org/download/${pdb}.cif`)
+    const parsed = await parseCif(await data.text())
+    const structure = Structure.ofData({ kind: 'mmCIF', data: CIF.schema.mmCIF(parsed.result.blocks[0]) })
+    return structure
+}
 
 
 export default class State {
 export default class State {
     regl: REGL.Regl
     regl: REGL.Regl
 
 
-    initRegl (container: HTMLDivElement) {
+    async initRegl (container: HTMLDivElement) {
         const regl = glContext.create({
         const regl = glContext.create({
             container,
             container,
             extensions: [
             extensions: [
                 'OES_texture_float',
                 'OES_texture_float',
                 'OES_texture_float_linear',
                 'OES_texture_float_linear',
                 'OES_element_index_uint',
                 'OES_element_index_uint',
-                // 'ext_disjoint_timer_query',
+                // 'EXT_disjoint_timer_query',
                 'EXT_blend_minmax',
                 'EXT_blend_minmax',
                 'ANGLE_instanced_arrays'
                 'ANGLE_instanced_arrays'
             ],
             ],
@@ -34,7 +57,9 @@ export default class State {
         })
         })
 
 
         const camera = Camera.create(regl, container, {
         const camera = Camera.create(regl, container, {
-            center: Vec3.create(0, 0, 0)
+            center: Vec3.create(0, 0, 0),
+            near: 0.01,
+            far: 1000
         })
         })
 
 
         const p1 = Vec3.create(0, 4, 0)
         const p1 = Vec3.create(0, 4, 0)
@@ -57,8 +82,6 @@ export default class State {
         Mat4.setTranslation(m4, p2)
         Mat4.setTranslation(m4, p2)
         Mat4.toArray(m4, transformArray2, 32)
         Mat4.toArray(m4, transformArray2, 32)
 
 
-
-
         const colorTexInfo = calculateTextureInfo(3, 3)
         const colorTexInfo = calculateTextureInfo(3, 3)
         const color = new Uint8Array(colorTexInfo.length)
         const color = new Uint8Array(colorTexInfo.length)
         color.set([
         color.set([
@@ -110,22 +133,44 @@ export default class State {
 
 
         const mesh2 = MeshRenderable.create(regl,
         const mesh2 = MeshRenderable.create(regl,
             {
             {
-                position: Attribute.create(regl, new Float32Array(box.vertices), { size: 3 }),
-                normal: Attribute.create(regl, new Float32Array(box.normals), { size: 3 }),
+                position: Attribute.create(regl, new Float32Array(sphere.vertices), { size: 3 }),
+                normal: Attribute.create(regl, new Float32Array(sphere.normals), { size: 3 }),
                 ...createTransformAttributes(regl, transformArray2)
                 ...createTransformAttributes(regl, transformArray2)
             },
             },
             {
             {
                 colorTex,
                 colorTex,
                 colorTexSize: [ colorTexInfo.width, colorTexInfo.height ],
                 colorTexSize: [ colorTexInfo.width, colorTexInfo.height ],
-                'light.position': Vec3.create(0, 0, -20),
+                'light.position': Vec3.create(0, 0, -100),
                 'light.color': Vec3.create(1.0, 1.0, 1.0),
                 'light.color': Vec3.create(1.0, 1.0, 1.0),
                 'light.ambient': Vec3.create(0.5, 0.5, 0.5),
                 'light.ambient': Vec3.create(0.5, 0.5, 0.5),
                 'light.falloff': 0,
                 'light.falloff': 0,
                 'light.radius': 500
                 'light.radius': 500
             },
             },
-            box.indices
+            // box.indices
         )
         )
 
 
+        function createSpacefills (structure: Structure) {
+            const spacefills: UnitRepresentation[] = []
+            const { atoms, units } = structure;
+            const unitIds = AtomSet.unitIds(atoms);
+            for (let i = 0, _i = unitIds.length; i < _i; i++) {
+                const unitId = unitIds[i];
+                const unit = units[unitId];
+                const atomGroup = AtomSet.unitGetByIndex(atoms, i);
+
+                const spacefill = Spacefill(regl)
+                spacefill.create(unit, atomGroup, {})
+                console.log('spacefill', spacefill)
+                spacefills.push(spacefill)
+            }
+            return spacefills
+        }
+
+        const structures = await getPdb('1crn')
+        const spacefills = createSpacefills(structures[0])
+
+        structures[0]
+
         const baseContext = regl({
         const baseContext = regl({
             context: {
             context: {
                 model: Mat4.identity(),
                 model: Mat4.identity(),
@@ -143,6 +188,7 @@ export default class State {
                 baseContext(() => {
                 baseContext(() => {
                     // console.log(ctx)
                     // console.log(ctx)
                     regl.clear({color: [0, 0, 0, 1]})
                     regl.clear({color: [0, 0, 0, 1]})
+                    spacefills.forEach(r => r.draw())
                     position.update(array => { array[0] = Math.random() })
                     position.update(array => { array[0] = Math.random() })
                     // points.update(a => { a.position[0] = Math.random() })
                     // points.update(a => { a.position[0] = Math.random() })
                     // mesh.draw()
                     // mesh.draw()

+ 3 - 3
src/apps/render-test/ui.tsx

@@ -7,16 +7,16 @@
 import * as React from 'react'
 import * as React from 'react'
 import State from './state'
 import State from './state'
 
 
-export default class Root extends React.Component<{ state: State }, { }> {
+export default class Root extends React.Component<{ state: State }, { initialized: boolean }> {
     private canvasContainer: HTMLDivElement | null = null;
     private canvasContainer: HTMLDivElement | null = null;
+    state = { initialized: false }
 
 
     componentDidMount() {
     componentDidMount() {
-        if (this.canvasContainer) this.props.state.initRegl(this.canvasContainer)
+        if (this.canvasContainer) this.props.state.initRegl(this.canvasContainer).then(() => this.setState({ initialized: true }))
     }
     }
 
 
     render() {
     render() {
         return <div ref={elm => this.canvasContainer = elm} style={{ position: 'absolute', top: 0, right: 0, left: 0, bottom: 0, overflow: 'hidden' }}>
         return <div ref={elm => this.canvasContainer = elm} style={{ position: 'absolute', top: 0, right: 0, left: 0, bottom: 0, overflow: 'hidden' }}>
-
         </div>
         </div>
     }
     }
 }
 }

+ 0 - 2
src/mol-geo/primitive/polyhedron.ts

@@ -88,7 +88,5 @@ export default function Polyhedron(_vertices: Helpers.NumberArray, _indices: Hel
                 }
                 }
             }
             }
         }
         }
-
-        console.log(v)
     }
     }
 }
 }

+ 41 - 0
src/mol-geo/representation/structure/index.ts

@@ -0,0 +1,41 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import { AtomGroup, AtomSet, Structure, Unit } from 'mol-model/structure';
+
+export interface RepresentationProps {
+
+}
+
+export interface UnitRepresentation {
+    create: (unit: Unit, atomGroup: AtomGroup, props: RepresentationProps) => boolean,
+    update: (props: RepresentationProps) => boolean,
+    draw: () => void
+}
+
+// export interface StructureRepresentation {
+//     create: (structure: Structure, props: RepresentationProps) => boolean,
+//     update: (props: RepresentationProps) => boolean
+// }
+
+export class StructureRepresentation {
+    constructor () {
+
+    }
+    create (structure: Structure, props: RepresentationProps) {
+        const { atoms, units } = structure;
+        const unitIds = AtomSet.unitIds(atoms);
+        for (let i = 0, _i = unitIds.length; i < _i; i++) {
+            const unitId = unitIds[i];
+            const unit = units[unitId];
+            const atomGroup = AtomSet.unitGetByIndex(atoms, i);
+
+        }
+
+        return true
+    }
+    update: (props: RepresentationProps) => false
+}

+ 106 - 0
src/mol-geo/representation/structure/spacefill.ts

@@ -0,0 +1,106 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import REGL = require('regl');
+import { MeshRenderable, Renderable } from 'mol-gl/renderable'
+import { createTransformAttributes } from 'mol-gl/renderable/util';
+import Attribute from 'mol-gl/attribute';
+import { calculateTextureInfo } from 'mol-gl/util';
+import Icosahedron from 'mol-geo/primitive/icosahedron'
+import { Vec3, Mat4 } from 'mol-math/linear-algebra'
+import { OrderedSet } from 'mol-data/int'
+import { Atom, AtomGroup, Unit } from 'mol-model/structure';
+import P from 'mol-model/structure/query/properties';
+import { RepresentationProps, UnitRepresentation } from './index';
+
+export default function Spacefill(regl: REGL.Regl): UnitRepresentation {
+    let vertices: Float32Array
+    let normals: Float32Array
+
+    const renderables: Renderable<any>[] = []
+
+    return {
+        create: (unit: Unit, atomGroup: AtomGroup, props: RepresentationProps) => {
+            const atomCount = OrderedSet.size(atomGroup.atoms)
+
+            const l = Atom.Location();
+            l.unit = unit;
+
+            const sphere = Icosahedron(1, 0)
+            const vertexCount = sphere.vertices.length / 3
+
+            vertices = new Float32Array(atomCount * vertexCount * 3)
+            normals = new Float32Array(atomCount * vertexCount * 3)
+
+            const v = Vec3.zero()
+            const m = Mat4.identity()
+
+            for (let i = 0; i < atomCount; i++) {
+                l.atom = OrderedSet.getAt(atomGroup.atoms, i)
+
+                v[0] = P.atom.x(l)
+                v[1] = P.atom.y(l)
+                v[2] = P.atom.z(l)
+                Mat4.setTranslation(m, v)
+
+                for (let j = 0; j < vertexCount; ++j) {
+                    Vec3.fromArray(v, sphere.vertices, j * 3)
+                    Vec3.transformMat4(v, v, m)
+                    Vec3.toArray(v, vertices, i * vertexCount * 3 + j * 3)
+                }
+
+                normals.set(sphere.normals, i * vertexCount * 3)
+            }
+
+            const transformArray = new Float32Array(16)
+            const m4 = Mat4.identity()
+            Mat4.toArray(m4, transformArray, 0)
+
+            const colorTexInfo = calculateTextureInfo(3, 3)
+            const color = new Uint8Array(colorTexInfo.length)
+            color.set([
+                0, 0, 255,
+                0, 255, 0,
+                255, 0, 0
+            ])
+            // console.log(color, colorTexInfo)
+            const colorTex = regl.texture({
+                width: colorTexInfo.width,
+                height: colorTexInfo.height,
+                format: 'rgb',
+                type: 'uint8',
+                wrapS: 'clamp',
+                wrapT: 'clamp',
+                data: color
+            })
+
+            const spheres = MeshRenderable.create(regl,
+                {
+                    position: Attribute.create(regl, new Float32Array(vertices), { size: 3 }),
+                    normal: Attribute.create(regl, new Float32Array(normals), { size: 3 }),
+                    ...createTransformAttributes(regl, transformArray)
+                },
+                {
+                    colorTex,
+                    colorTexSize: [ colorTexInfo.width, colorTexInfo.height ],
+                    'light.position': Vec3.create(0, 0, -100),
+                    'light.color': Vec3.create(1.0, 1.0, 1.0),
+                    'light.ambient': Vec3.create(0.5, 0.5, 0.5),
+                    'light.falloff': 0,
+                    'light.radius': 500
+                }
+            )
+
+            // console.log({ vertices, normals, vertexCount, atomCount })
+
+            renderables.push(spheres)
+
+            return true
+        },
+        update: (props: RepresentationProps) => false,
+        draw: () => renderables.forEach(r => r.draw())
+    }
+}

+ 5 - 1
src/mol-gl/attribute.ts

@@ -46,6 +46,7 @@ interface Attribute<T extends Helpers.TypedArray> {
     set(index: number, ...values: number[]): void
     set(index: number, ...values: number[]): void
     update(mutator: Attribute.Mutator<T>): void
     update(mutator: Attribute.Mutator<T>): void
     reload(): void
     reload(): void
+    destroy(): void
 }
 }
 
 
 interface AttributeProps {
 interface AttributeProps {
@@ -58,6 +59,8 @@ interface AttributeProps {
 namespace Attribute {
 namespace Attribute {
     export type Mutator<T extends Helpers.TypedArray> = (data: T) => (UpdateInfo | void)
     export type Mutator<T extends Helpers.TypedArray> = (data: T) => (UpdateInfo | void)
     export type UpdateInfo = boolean | { offset: number, count: number }
     export type UpdateInfo = boolean | { offset: number, count: number }
+    export type ArrayCell<T> = { array: ReferenceCell<T> }
+    export type ReferenceCell<T> = { readonly version: number, readonly value: T }
 
 
     export function create<T extends Helpers.TypedArray>(regl: REGL.Regl, array: T, props: AttributeProps): Attribute<T> {
     export function create<T extends Helpers.TypedArray>(regl: REGL.Regl, array: T, props: AttributeProps): Attribute<T> {
         const itemSize = props.size
         const itemSize = props.size
@@ -94,7 +97,8 @@ namespace Attribute {
                 mutator(_array)
                 mutator(_array)
                 buffer(_array)
                 buffer(_array)
             },
             },
-            reload: () => buffer(_array)
+            reload: () => buffer(_array),
+            destroy: () => buffer.destroy()
         }
         }
     }
     }
 }
 }

+ 7 - 7
src/mol-gl/renderable/mesh.ts

@@ -34,15 +34,15 @@ namespace Mesh {
     export type Attributes = { [K in keyof Data]: Attribute<Data[K]> }
     export type Attributes = { [K in keyof Data]: Attribute<Data[K]> }
 
 
     export function create(regl: REGL.Regl, attributes: Attributes, uniforms: Uniforms, elements?: Helpers.UintArray): Renderable<Data> {
     export function create(regl: REGL.Regl, attributes: Attributes, uniforms: Uniforms, elements?: Helpers.UintArray): Renderable<Data> {
-        console.log('mesh', {
-            count: attributes.position.getCount(),
-            instances: attributes.transformColumn0.getCount(),
-            attributes,
-            uniforms
-        })
+        // console.log('mesh', {
+        //     count: attributes.position.getCount(),
+        //     instances: attributes.transformColumn0.getCount(),
+        //     attributes,
+        //     uniforms
+        // })
         const instanceCount = attributes.transformColumn0.getCount()
         const instanceCount = attributes.transformColumn0.getCount()
         const instanceId = fillSerial(new Float32Array(instanceCount))
         const instanceId = fillSerial(new Float32Array(instanceCount))
-        console.log(instanceId)
+        // console.log(instanceId)
         const command = regl({
         const command = regl({
             ...MeshShaders,
             ...MeshShaders,
             uniforms: {
             uniforms: {

+ 1 - 1
src/mol-gl/shader/mesh.frag

@@ -4,7 +4,7 @@
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
  */
 
 
-precision mediump float;
+precision highp float;
 
 
 struct Light {
 struct Light {
     vec3 position;
     vec3 position;

+ 1 - 1
src/mol-gl/shader/mesh.vert

@@ -6,7 +6,7 @@
 
 
 #define INSTANCE_COLOR
 #define INSTANCE_COLOR
 
 
-precision mediump float;
+precision highp float;
 
 
 uniform mat4 projection, model, view;
 uniform mat4 projection, model, view;
 
 

+ 60 - 4
src/mol-math/linear-algebra/3d.ts

@@ -897,6 +897,9 @@ export namespace Vec3 {
         return out;
         return out;
     }
     }
 
 
+    /**
+     * Performs a linear interpolation between two Vec3's
+     */
     export function lerp(out: Vec3, a: Vec3, b: Vec3, t: number) {
     export function lerp(out: Vec3, a: Vec3, b: Vec3, t: number) {
         const ax = a[0],
         const ax = a[0],
             ay = a[1],
             ay = a[1],
@@ -907,12 +910,65 @@ export namespace Vec3 {
         return out;
         return out;
     }
     }
 
 
+    /**
+     * Performs a hermite interpolation with two control points
+     */
+    export function hermite(out: Vec3, a: Vec3, b: Vec3, c: Vec3, d: Vec3, t: number) {
+        const factorTimes2 = t * t;
+        const factor1 = factorTimes2 * (2 * t - 3) + 1;
+        const factor2 = factorTimes2 * (t - 2) + t;
+        const factor3 = factorTimes2 * (t - 1);
+        const factor4 = factorTimes2 * (3 - 2 * t);
+
+        out[0] = a[0] * factor1 + b[0] * factor2 + c[0] * factor3 + d[0] * factor4;
+        out[1] = a[1] * factor1 + b[1] * factor2 + c[1] * factor3 + d[1] * factor4;
+        out[2] = a[2] * factor1 + b[2] * factor2 + c[2] * factor3 + d[2] * factor4;
+
+        return out;
+    }
+
+    /**
+     * Performs a bezier interpolation with two control points
+     */
+    export function bezier(out: Vec3, a: Vec3, b: Vec3, c: Vec3, d: Vec3, t: number) {
+        const inverseFactor = 1 - t;
+        const inverseFactorTimesTwo = inverseFactor * inverseFactor;
+        const factorTimes2 = t * t;
+        const factor1 = inverseFactorTimesTwo * inverseFactor;
+        const factor2 = 3 * t * inverseFactorTimesTwo;
+        const factor3 = 3 * factorTimes2 * inverseFactor;
+        const factor4 = factorTimes2 * t;
+
+        out[0] = a[0] * factor1 + b[0] * factor2 + c[0] * factor3 + d[0] * factor4;
+        out[1] = a[1] * factor1 + b[1] * factor2 + c[1] * factor3 + d[1] * factor4;
+        out[2] = a[2] * factor1 + b[2] * factor2 + c[2] * factor3 + d[2] * factor4;
+
+        return out;
+    }
+
+    /**
+     * Generates a random vector with the given scale
+     */
+    export function random(out: Vec3, scale: number) {
+        const r = Math.random() * 2.0 * Math.PI;
+        const z = (Math.random() * 2.0) - 1.0;
+        const zScale = Math.sqrt(1.0-z*z) * scale;
+
+        out[0] = Math.cos(r) * zScale;
+        out[1] = Math.sin(r) * zScale;
+        out[2] = z * scale;
+        return out;
+    }
+
+    /**
+     * Transforms the Vec3 with a Mat4. 4th vector component is implicitly '1'
+     */
     export function transformMat4(out: Vec3, a: Vec3, m: Mat4) {
     export function transformMat4(out: Vec3, a: Vec3, m: Mat4) {
         const x = a[0], y = a[1], z = a[2],
         const x = a[0], y = a[1], z = a[2],
-            w = (m[3] * x + m[7] * y + m[11] * z + m[15]) || 1.0;
-        out[0] = (m[0] * x + m[4] * y + m[8] * z + m[12]) / w;
-        out[1] = (m[1] * x + m[5] * y + m[9] * z + m[13]) / w;
-        out[2] = (m[2] * x + m[6] * y + m[10] * z + m[14]) / w;
+            w = 1 / ((m[3] * x + m[7] * y + m[11] * z + m[15]) || 1.0);
+        out[0] = (m[0] * x + m[4] * y + m[8] * z + m[12]) * w;
+        out[1] = (m[1] * x + m[5] * y + m[9] * z + m[13]) * w;
+        out[2] = (m[2] * x + m[6] * y + m[10] * z + m[14]) * w;
         return out;
         return out;
     }
     }