Skip to content
Snippets Groups Projects
Commit 2d21bd7c authored by Alexander Rose's avatar Alexander Rose
Browse files

wip, coloring

parent 612c5f78
No related branches found
No related tags found
No related merge requests found
......@@ -47,12 +47,12 @@ export default class State {
const structures = await getStructuresFromPdbId(pdbId)
const struct = Symmetry.buildAssembly(structures[0], '1')
const structPointRepr = StructureRepresentation(Point)
await Run(structPointRepr.create(struct))
structPointRepr.renderObjects.forEach(viewer.add)
// const structPointRepr = StructureRepresentation(Point)
// await Run(structPointRepr.create(struct))
// structPointRepr.renderObjects.forEach(viewer.add)
const structSpacefillRepr = StructureRepresentation(Spacefill)
await Run(structSpacefillRepr.create(struct))
await Run(structSpacefillRepr.create(struct, { detail: 2 }))
structSpacefillRepr.renderObjects.forEach(viewer.add)
this.loading.next(false)
......
/**
* Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
export { ElementColor } from './structure/element';
export function hexColorToArray(hexColor: number, array: Helpers.NumberArray, offset: number) {
array[ offset ] = (hexColor >> 16 & 255) / 255
array[ offset + 1 ] = (hexColor >> 8 & 255) / 255
array[ offset + 2 ] = (hexColor & 255) / 255
}
\ No newline at end of file
/**
* Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
import { ElementSymbol } from 'mol-model/structure/model/types';
// from Jmol http://jmol.sourceforge.net/jscolors/ (or 0xFFFFFF)
export const ElementColors: { [k: string]: number } = {
'H': 0xFFFFFF, 'HE': 0xD9FFFF, 'LI': 0xCC80FF, 'BE': 0xC2FF00, 'B': 0xFFB5B5, 'C': 0x909090, 'N': 0x3050F8, 'O': 0xFF0D0D, 'F': 0x90E050, 'NE': 0xB3E3F5, 'NA': 0xAB5CF2, 'MG': 0x8AFF00, 'AL': 0xBFA6A6, 'SI': 0xF0C8A0, 'P': 0xFF8000, 'S': 0xFFFF30, 'CL': 0x1FF01F, 'AR': 0x80D1E3, 'K': 0x8F40D4, 'CA': 0x3DFF00, 'SC': 0xE6E6E6, 'TI': 0xBFC2C7, 'V': 0xA6A6AB, 'CR': 0x8A99C7, 'MN': 0x9C7AC7, 'FE': 0xE06633, 'CO': 0xF090A0, 'NI': 0x50D050, 'CU': 0xC88033, 'ZN': 0x7D80B0, 'GA': 0xC28F8F, 'GE': 0x668F8F, 'AS': 0xBD80E3, 'SE': 0xFFA100, 'BR': 0xA62929, 'KR': 0x5CB8D1, 'RB': 0x702EB0, 'SR': 0x00FF00, 'Y': 0x94FFFF, 'ZR': 0x94E0E0, 'NB': 0x73C2C9, 'MO': 0x54B5B5, 'TC': 0x3B9E9E, 'RU': 0x248F8F, 'RH': 0x0A7D8C, 'PD': 0x006985, 'AG': 0xC0C0C0, 'CD': 0xFFD98F, 'IN': 0xA67573, 'SN': 0x668080, 'SB': 0x9E63B5, 'TE': 0xD47A00, 'I': 0x940094, 'XE': 0x940094, 'CS': 0x57178F, 'BA': 0x00C900, 'LA': 0x70D4FF, 'CE': 0xFFFFC7, 'PR': 0xD9FFC7, 'ND': 0xC7FFC7, 'PM': 0xA3FFC7, 'SM': 0x8FFFC7, 'EU': 0x61FFC7, 'GD': 0x45FFC7, 'TB': 0x30FFC7, 'DY': 0x1FFFC7, 'HO': 0x00FF9C, 'ER': 0x00E675, 'TM': 0x00D452, 'YB': 0x00BF38, 'LU': 0x00AB24, 'HF': 0x4DC2FF, 'TA': 0x4DA6FF, 'W': 0x2194D6, 'RE': 0x267DAB, 'OS': 0x266696, 'IR': 0x175487, 'PT': 0xD0D0E0, 'AU': 0xFFD123, 'HG': 0xB8B8D0, 'TL': 0xA6544D, 'PB': 0x575961, 'BI': 0x9E4FB5, 'PO': 0xAB5C00, 'AT': 0x754F45, 'RN': 0x428296, 'FR': 0x420066, 'RA': 0x007D00, 'AC': 0x70ABFA, 'TH': 0x00BAFF, 'PA': 0x00A1FF, 'U': 0x008FFF, 'NP': 0x0080FF, 'PU': 0x006BFF, 'AM': 0x545CF2, 'CM': 0x785CE3, 'BK': 0x8A4FE3, 'CF': 0xA136D4, 'ES': 0xB31FD4, 'FM': 0xB31FBA, 'MD': 0xB30DA6, 'NO': 0xBD0D87, 'LR': 0xC70066, 'RF': 0xCC0059, 'DB': 0xD1004F, 'SG': 0xD90045, 'BH': 0xE00038, 'HS': 0xE6002E, 'MT': 0xEB0026, 'DS': 0xFFFFFF, 'RG': 0xFFFFFF, 'CN': 0xFFFFFF, 'UUT': 0xFFFFFF, 'FL': 0xFFFFFF, 'UUP': 0xFFFFFF, 'LV': 0xFFFFFF, 'UUH': 0xFFFFFF, 'D': 0xFFFFC0, 'T': 0xFFFFA0
}
const DefaultElementColor = 0xFFFFFF
export function ElementColor(element: ElementSymbol): number {
const c = ElementColors[element as any as string];
return c === void 0 ? DefaultElementColor : c
}
\ No newline at end of file
......@@ -14,6 +14,7 @@ import { ChunkedArray } from 'mol-data/util';
import { Unit, ElementGroup } from 'mol-model/structure';
import { RepresentationProps, UnitsRepresentation } from './index';
import { Task } from 'mol-task'
import { VdwRadius } from 'mol-model/structure/model/properties/atomic';
export const DefaultPointProps = {
......@@ -23,6 +24,7 @@ export type PointProps = Partial<typeof DefaultPointProps>
export default function Point(): UnitsRepresentation<PointProps> {
const renderObjects: RenderObject[] = []
const vertices = ChunkedArray.create(Float32Array, 3, 1024, 2048);
const sizes = ChunkedArray.create(Float32Array, 1, 1024, 2048);
return {
renderObjects,
......@@ -30,10 +32,12 @@ export default function Point(): UnitsRepresentation<PointProps> {
// const l = Element.Location();
const { x, y, z } = units[0].model.conformation
const { type_symbol } = units[0].model.hierarchy.atoms
const elementCount = OrderedSet.size(elementGroup.elements)
for (let i = 0; i < elementCount; i++) {
const e = OrderedSet.getAt(elementGroup.elements, i)
ChunkedArray.add3(vertices, x[e], y[e], z[e])
ChunkedArray.add(sizes, VdwRadius(type_symbol.value(e)))
if (i % 10 === 0 && ctx.shouldUpdate) {
await ctx.update({ message: 'Point', current: i, max: elementCount });
......@@ -51,6 +55,7 @@ export default function Point(): UnitsRepresentation<PointProps> {
const points = createRenderObject('point', {
position: ValueCell.create(ChunkedArray.compact(vertices, true) as Float32Array),
size: ValueCell.create(ChunkedArray.compact(sizes, true) as Float32Array),
color,
transform: ValueCell.create(transformArray),
......
......@@ -7,7 +7,7 @@
import { ValueCell } from 'mol-util/value-cell'
import { createRenderObject, RenderObject } from 'mol-gl/scene'
import { createColorTexture } from 'mol-gl/util';
// import { createColorTexture } from 'mol-gl/util';
import { Vec3, Mat4 } from 'mol-math/linear-algebra'
import { OrderedSet } from 'mol-data/int'
import { Unit, ElementGroup } from 'mol-model/structure';
......@@ -15,9 +15,10 @@ 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';
export const DefaultSpacefillProps = {
detail: 0
}
export type SpacefillProps = Partial<typeof DefaultSpacefillProps>
......@@ -27,6 +28,7 @@ export default function Spacefill(): UnitsRepresentation<SpacefillProps> {
return {
renderObjects,
create: (units: ReadonlyArray<Unit>, elementGroup: ElementGroup, props: SpacefillProps = {}) => Task.create('Spacefill', async ctx => {
const { detail } = { ...DefaultSpacefillProps, ...props }
const meshBuilder = MeshBuilder.create()
const v = Vec3.zero()
......@@ -42,7 +44,11 @@ export default function Spacefill(): UnitsRepresentation<SpacefillProps> {
v[2] = z[e]
Mat4.setTranslation(m, v)
meshBuilder.addIcosahedron(m, { radius: VdwRadius(type_symbol.value(e)), detail: 0 })
meshBuilder.addIcosahedron(m, {
radius: VdwRadius(type_symbol.value(e)),
color: ElementColor(type_symbol.value(e)),
detail
})
if (i % 10 === 0 && ctx.shouldUpdate) {
await ctx.update({ message: 'Spacefill', current: i, max: elementCount });
......@@ -55,15 +61,16 @@ export default function Spacefill(): UnitsRepresentation<SpacefillProps> {
Mat4.toArray(units[i].operator.matrix, transformArray, i * 16)
}
const color = ValueCell.create(createColorTexture(unitsCount))
color.ref.value.set([ 0, 0, 255 ])
// const color = ValueCell.create(createColorTexture(unitsCount))
// color.ref.value.set([ 0, 0, 255 ])
const mesh = meshBuilder.getMesh()
console.log(mesh)
const spheres = createRenderObject('mesh', {
position: mesh.vertexBuffer,
normal: mesh.normalBuffer,
color,
color: { '@type': 'attribute', value: (mesh as any).colorBuffer },
transform: ValueCell.create(transformArray),
elements: mesh.indexBuffer,
......
......@@ -9,15 +9,18 @@ import { Vec3, Mat4 } from 'mol-math/linear-algebra';
import { ChunkedArray } from 'mol-data/util';
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 ElementId = { id?: number }
type ElementProps = { id?: number, color?: number }
export interface MeshBuilder {
add(t: Mat4, _vertices: Float32Array, _normals: Float32Array, _indices?: Uint32Array): number
addBox(t: Mat4, props?: BoxProps & ElementId): number
addIcosahedron(t: Mat4, props?: IcosahedronProps & ElementId): number
addBox(t: Mat4, props?: BoxProps & ElementProps): number
addCylinder(t: Mat4, props?: CylinderProps & ElementProps): number
addIcosahedron(t: Mat4, props?: IcosahedronProps & ElementProps): number
getMesh(): Mesh
}
......@@ -29,6 +32,7 @@ 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);
......@@ -36,7 +40,7 @@ export namespace MeshBuilder {
ChunkedArray.compact(indices, true)
const add = (t: Mat4, _vertices: Float32Array, _normals: Float32Array, _indices: Uint32Array) => {
const add = (t: Mat4, _vertices: Float32Array, _normals: Float32Array, _indices: Uint32Array, _colors?: Float32Array) => {
const { elementCount, elementSize } = vertices
for (let i = 0, il = _vertices.length; i < il; i += 3) {
// position
......@@ -47,6 +51,11 @@ export namespace MeshBuilder {
Vec3.fromArray(tmpV, _normals, i)
// 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]);
}
}
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);
......@@ -56,23 +65,39 @@ export namespace MeshBuilder {
return {
add,
addBox: (t: Mat4, props?: BoxProps & ElementId) => {
addBox: (t: Mat4, props?: BoxProps & ElementProps) => {
const box = Box(props)
return add(t, box.vertices, box.normals, box.indices)
},
addIcosahedron: (t: Mat4, props?: IcosahedronProps & ElementId) => {
addCylinder: (t: Mat4, props?: CylinderProps & ElementProps) => {
const cylinder = Cylinder(props)
return add(t, cylinder.vertices, cylinder.normals, cylinder.indices)
},
addIcosahedron: (t: Mat4, props?: IcosahedronProps & ElementProps) => {
const icosahedron = Icosahedron(props)
return add(t, icosahedron.vertices, icosahedron.normals, icosahedron.indices)
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, colors)
},
getMesh: () => {
return {
const mesh = {
vertexCount: vertices.elementCount,
triangleCount: indices.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),
normalsComputed: true,
}
if (colors.elementCount) {
mesh.colorBuffer = ValueCell.create(ChunkedArray.compact(colors, true) as Float32Array)
}
return mesh
}
}
}
......
......@@ -17,12 +17,17 @@ type Mesh = 'mesh'
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
namespace Mesh {
export type Data = {
position: ValueCell<Float32Array>
normal: ValueCell<Float32Array>
readonly color: Color
transform: ValueCell<Float32Array>
color: ValueCell<ColorTexture>
elements: ValueCell<Uint32Array>
instanceCount: number
......@@ -30,22 +35,29 @@ namespace Mesh {
positionCount: number
}
export function create(regl: REGL.Regl, data: Data, uniforms: Uniforms): Renderable {
export function create(regl: REGL.Regl, data: Data, _uniforms: Uniforms): Renderable {
const instanceId = ValueCell.create(fillSerial(new Float32Array(data.instanceCount)))
const uniforms = {
objectId: _uniforms.objectId || 0,
instanceCount: data.instanceCount,
..._uniforms
}
if (data.color['@type'] === 'instance' || data.color['@type'] === 'element') {
Object.assign(uniforms, createColorUniforms(regl, data.color.value as ValueCell<ColorTexture>))
}
const attributes = getBuffers({
instanceId: Attribute.create(regl, instanceId, data.instanceCount, { size: 1, divisor: 1 }),
position: Attribute.create(regl, data.position, data.positionCount, { size: 3 }),
normal: Attribute.create(regl, data.normal, data.positionCount, { size: 3 }),
...createTransformAttributes(regl, data.transform, data.instanceCount)
})
if (data.color['@type'] === 'attribute') {
attributes.color = Attribute.create(regl, data.color.value as ValueCell<Float32Array>, data.positionCount, { size: 3 }).buffer
}
const command = regl({
...MeshShaders,
uniforms: {
objectId: uniforms.objectId || 0,
instanceCount: data.instanceCount,
...createColorUniforms(regl, data.color),
...uniforms
},
attributes: getBuffers({
instanceId: Attribute.create(regl, instanceId, data.instanceCount, { size: 1, divisor: 1 }),
position: Attribute.create(regl, data.position, data.positionCount, { size: 3 }),
normal: Attribute.create(regl, data.normal, data.positionCount, { size: 3 }),
...createTransformAttributes(regl, data.transform, data.instanceCount)
}),
uniforms,
attributes,
elements: regl.elements({
data: data.elements.ref.value,
primitive: 'triangles',
......
......@@ -17,6 +17,7 @@ type Point = 'point'
namespace Point {
export type Data = {
position: ValueCell<Float32Array>
size?: ValueCell<Float32Array>
transform: ValueCell<Float32Array>
instanceCount: number
......@@ -25,13 +26,17 @@ namespace Point {
export function create(regl: REGL.Regl, data: Data): Renderable {
const instanceId = ValueCell.create(fillSerial(new Float32Array(data.instanceCount)))
const attributes = getBuffers({
instanceId: Attribute.create(regl, instanceId, data.instanceCount, { size: 1, divisor: 1 }),
position: Attribute.create(regl, data.position, data.positionCount, { size: 3 }),
...createTransformAttributes(regl, data.transform, data.positionCount)
})
if (data.size) {
attributes.size = Attribute.create(regl, data.size, data.positionCount, { size: 1 }).buffer
}
const command = regl({
...PointShaders,
attributes: getBuffers({
instanceId: Attribute.create(regl, instanceId, data.instanceCount, { size: 1, divisor: 1 }),
position: Attribute.create(regl, data.position, data.positionCount, { size: 3 }),
...createTransformAttributes(regl, data.transform, data.positionCount)
}),
attributes,
count: data.positionCount,
instances: data.instanceCount,
primitive: 'points'
......
......@@ -60,7 +60,7 @@ void main() {
vec3 L = normalize(lightVector); // light direction
vec3 V = normalize(vViewPosition); // eye direction
vec3 N = normalize(vNormal); // surface normal
vec3 N = normalize(-vNormal); // surface normal
// compute our diffuse & specular terms
float specular = phongSpecular(L, V, N, shininess) * specularScale * falloff;
......@@ -70,7 +70,8 @@ void main() {
// add the lighting
vec3 color = vColor * (diffuse + ambient) + specular;
gl_FragColor.rgb = N;
// gl_FragColor.rgb = N;
// gl_FragColor.rgb = vec3(1.0, 0.0, 0.0);
gl_FragColor.rgb = color;
gl_FragColor.a = 1.0;
}
\ No newline at end of file
......@@ -4,7 +4,8 @@
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
#define INSTANCE_COLOR
#define ATTRIBUTE_COLOR
// #define INSTANCE_COLOR
precision highp float;
......@@ -52,7 +53,6 @@ void main(){
vViewPosition = mvPosition.xyz;
gl_Position = projection * mvPosition;
// TODO do on CPU side
mat3 normalMatrix = transpose(inverse(mat3(modelView)));
vNormal = normalize(normalMatrix * normal);
}
\ No newline at end of file
......@@ -293,6 +293,7 @@ namespace Mat4 {
return mul(out, mul(out, a, b), c);
}
/** Translate a Mat4 by the given Vec3 */
export function translate(out: Mat4, a: Mat4, v: Vec3) {
const x = v[0], y = v[1], z = v[2];
let a00: number, a01: number, a02: number, a03: number,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment