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

wip, added renderer, removed regl dep from geo

parent ebf704e4
No related branches found
No related tags found
No related merge requests found
......@@ -4,23 +4,18 @@
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
import REGL = require('regl');
import { ValueBox } from 'mol-util/value-cell'
import * as glContext from 'mol-gl/context'
import { Camera } from 'mol-gl/camera'
import { Vec3, Mat4 } from 'mol-math/linear-algebra'
import { PointRenderable, MeshRenderable } from 'mol-gl/renderable'
import Model from 'mol-gl/model';
import { calculateTextureInfo } from 'mol-gl/util';
import { createRenderer, createRenderObject, RenderObject } from 'mol-gl/renderer'
import { createColorTexture } from 'mol-gl/util';
import Icosahedron from 'mol-geo/primitive/icosahedron'
import Box from 'mol-geo/primitive/box'
import Spacefill from 'mol-geo/representation/structure/spacefill'
import CIF from 'mol-io/reader/cif'
import { Run } from 'mol-task'
// 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)
......@@ -39,35 +34,12 @@ async function getPdb(pdb: string) {
import mcubes from './mcubes'
export default class State {
regl: REGL.Regl
async initRegl (container: HTMLDivElement) {
const regl = glContext.create({
container,
extensions: [
'OES_texture_float',
'OES_texture_float_linear',
'OES_element_index_uint',
// 'EXT_disjoint_timer_query',
'EXT_blend_minmax',
'ANGLE_instanced_arrays'
],
// profile: true
})
const camera = Camera.create(regl, container, {
center: Vec3.create(0, 0, 0),
near: 0.01,
far: 1000
})
async initRenderer (container: HTMLDivElement) {
const renderer = createRenderer(container)
const p1 = Vec3.create(0, 4, 0)
const p2 = Vec3.create(-3, 0, 0)
const model1 = Model(regl)
const model2 = Model(regl, { position: p1 })
const model3 = Model(regl, { position: p2 })
const position = ValueBox(new Float32Array([0, -1, 0, -1, 0, 0, 1, 1, 0]))
const normal = ValueBox(new Float32Array([0, 0, 0, 0, 0, 0, 0, 0, 0]))
......@@ -81,43 +53,23 @@ export default class State {
Mat4.setTranslation(m4, p2)
Mat4.toArray(m4, transformArray2.value, 32)
const colorTexInfo = calculateTextureInfo(3, 3)
const color = new Uint8Array(colorTexInfo.length)
color.set([
const color = ValueBox(createColorTexture(3))
color.value.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
})
// position.update((array: Float32Array) => {
// positionFromModel({}, array, 0)
// })
const points = PointRenderable.create(regl, {
const points = createRenderObject('point', {
position,
transform: transformArray1
})
const mesh = MeshRenderable.create(regl,
{
const mesh = createRenderObject('mesh', {
position,
normal,
color,
transform: transformArray2
},
{
colorTex,
colorTexSize: [ colorTexInfo.width, colorTexInfo.height ]
}
)
})
const sphere = Icosahedron(1, 1)
console.log(sphere)
......@@ -125,7 +77,7 @@ export default class State {
const box = Box(1, 1, 1, 1, 1, 1)
console.log(box)
const points2 = PointRenderable.create(regl, {
const points2 = createRenderObject('point', {
position: ValueBox(new Float32Array(box.vertices)),
transform: transformArray1
})
......@@ -133,61 +85,21 @@ export default class State {
let rr = 1;
function cubesF(x: number, y: number, z: number) {
return x * x + y * y + z * z - rr * rr;
// const a = ca;
// const t = (x + y + z + a);
// return x * x * x + y * y * y + z * z * z + a * a * a - t * t * t;
}
let cubes = await mcubes(cubesF);
const makeCubesMesh = () => MeshRenderable.create(regl,
{
const makeCubesMesh = () => createRenderObject('mesh', {
position: cubes.surface.vertexBuffer,
normal: cubes.surface.normalBuffer as any,
transform: transformArray1
},
{
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
},
cubes.surface.indexBuffer.value
);
let mesh2 = makeCubesMesh();
// const makeCubes = async () => {
// rr = Math.random();
// cubes = await mcubes(cubesF, cubes);
// mesh2 = makeCubesMesh();
// setTimeout(makeCubes, 1000 / 15);
// };
// makeCubes();
// 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 }),
// ...createTransformAttributes(regl, transformArray1)
// },
// {
// colorTex,
// colorTexSize: [ colorTexInfo.width, colorTexInfo.height ],
// 'light.position': Vec3.create(0, 0, -20),
// '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
// },
// box.indices
// )
color,
transform: transformArray1,
}, cubes.surface.indexBuffer.value);
const mesh2 = makeCubesMesh();
renderer.add(mesh2)
function createSpacefills (structure: Structure) {
const spacefills: UnitRepresentation[] = []
const spacefills: RenderObject[] = []
const { atoms, units } = structure;
const unitIds = AtomSet.unitIds(atoms);
for (let i = 0, _i = unitIds.length; i < _i; i++) {
......@@ -195,57 +107,16 @@ export default class State {
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)
const spacefill = Spacefill()
spacefills.push(...spacefill.create(unit, atomGroup, {}))
}
return spacefills
}
const structures = await getPdb('1crn')
const spacefills = createSpacefills(structures[0])
spacefills.forEach(renderer.add)
structures[0]
const baseContext = regl({
context: {
model: Mat4.identity(),
transform: Mat4.setTranslation(Mat4.identity(), Vec3.create(6, 0, 0))
},
uniforms: {
model: regl.context('model' as any),
transform: regl.context('transform' as any),
}
})
regl.frame((ctx) => {
camera.update((state: any) => {
if (!camera.isDirty()) return
baseContext(() => {
// console.log(ctx)
regl.clear({color: [0, 0, 0, 1]})
spacefills.forEach(r => r.draw())
// position.update(array => { array[0] = Math.random() })
// points.update(a => { a.position[0] = Math.random() })
// mesh.draw()
// points.draw()
mesh2.draw()
// points2.draw()
// model1({}, ({ transform }) => {
// points.draw()
// })
// model2({}, ({ transform }) => {
// points.draw()
// model3({ transform }, () => {
// points.draw()
// })
// })
})
}, undefined)
})
this.regl = regl
renderer.frame()
}
constructor() {
......
......@@ -12,7 +12,7 @@ export default class Root extends React.Component<{ state: State }, { initialize
state = { initialized: false }
componentDidMount() {
if (this.canvasContainer) this.props.state.initRegl(this.canvasContainer).then(() => this.setState({ initialized: true }))
if (this.canvasContainer) this.props.state.initRenderer(this.canvasContainer).then(() => this.setState({ initialized: true }))
}
render() {
......
......@@ -5,15 +5,15 @@
*/
import { AtomGroup, AtomSet, Structure, Unit } from 'mol-model/structure';
import { RenderObject } from 'mol-gl/renderer';
export interface RepresentationProps {
}
export interface UnitRepresentation {
create: (unit: Unit, atomGroup: AtomGroup, props: RepresentationProps) => boolean,
create: (unit: Unit, atomGroup: AtomGroup, props: RepresentationProps) => RenderObject[],
update: (props: RepresentationProps) => boolean,
draw: () => void
}
// export interface StructureRepresentation {
......
......@@ -4,11 +4,10 @@
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
import REGL = require('regl');
import { ValueBox } from 'mol-util/value-cell'
import { MeshRenderable, Renderable } from 'mol-gl/renderable'
import { calculateTextureInfo } from 'mol-gl/util';
import { createRenderObject, RenderObject } from 'mol-gl/renderer'
import { createColorTexture } 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'
......@@ -16,11 +15,11 @@ 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 {
export default function Spacefill(): UnitRepresentation {
let vertices: Float32Array
let normals: Float32Array
const renderables: Renderable<any>[] = []
const renderObjects: RenderObject[] = []
return {
create: (unit: Unit, atomGroup: AtomGroup, props: RepresentationProps) => {
......@@ -59,48 +58,25 @@ export default function Spacefill(regl: REGL.Regl): UnitRepresentation {
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,
const color = ValueBox(createColorTexture(1))
color.value.set([ 0, 0, 255 ])
const spheres = createRenderObject(
'mesh',
{
position: ValueBox(new Float32Array(vertices)),
normal: ValueBox(new Float32Array(normals)),
color,
transform: ValueBox(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)
renderObjects.push(spheres)
return true
return renderObjects
},
update: (props: RepresentationProps) => false,
draw: () => renderables.forEach(r => r.draw())
update: (props: RepresentationProps) => false
}
}
......@@ -82,7 +82,7 @@ export namespace Camera {
const right = Vec3.create(1, 0, 0)
const front = Vec3.create(0, 0, 1)
let dirty = false
let dirty = true
let ddistance = 0
let prevX = 0
......
......@@ -16,6 +16,9 @@ export type AttributesBuffers<T extends AttributesData> = { [K in keyof T]: REGL
export interface Renderable<T extends AttributesData> {
draw(): void
// isPicking: () => boolean
// isVisible: () => boolean
// isTransparent: () => boolean
}
export { PointRenderable, MeshRenderable }
\ No newline at end of file
......@@ -8,7 +8,8 @@ import REGL = require('regl');
import { ValueBox } from 'mol-util/value-cell'
import { Renderable } from '../renderable'
import { getBuffers, createTransformAttributes, fillSerial } from './util'
import { ColorTexture } from '../util'
import { getBuffers, createTransformAttributes, fillSerial, createColorUniforms } from './util'
import Attribute from '../attribute';
import { MeshShaders } from '../shaders'
......@@ -21,6 +22,7 @@ namespace Mesh {
position: { type: Float32Array, itemSize: 3 }
normal: { type: Float32Array, itemSize: 3 }
transform: { type: Float32Array, itemSize: 16 }
color: { type: ColorTexture, itemSize: 16 }
}
export type Data = { [K in keyof DataType]: DataType[K]['type'] }
export type BoxedData = { [K in keyof Data]: ValueBox<Data[K]> }
......@@ -40,6 +42,7 @@ namespace Mesh {
uniforms: {
objectId: uniforms.objectId || 0,
instanceCount,
...createColorUniforms(regl, data.color),
...uniforms
},
attributes: getBuffers({
......
......@@ -7,6 +7,7 @@
import REGL = require('regl');
import { ValueBox } from 'mol-util/value-cell'
import { ColorTexture } from '../util';
import { Attributes, AttributesData, AttributesBuffers } from '../renderable'
import Attribute from '../attribute'
......@@ -23,6 +24,22 @@ export function createTransformAttributes (regl: REGL.Regl, transform: ValueBox<
}
}
export function createColorUniforms (regl: REGL.Regl, color: ValueBox<ColorTexture>) {
const colorTex = regl.texture({
width: color.value.width,
height: color.value.height,
format: 'rgb',
type: 'uint8',
wrapS: 'clamp',
wrapT: 'clamp',
data: color.value
})
return {
colorTex,
colorTexSize: [ color.value.width, color.value.height ]
}
}
export function getBuffers<T extends AttributesData>(attributes: Attributes<T>): AttributesBuffers<T> {
const buffers: AttributesBuffers<any> = {}
for (const k of Object.keys(attributes)) {
......
/**
* 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 * as glContext from './context'
import { Camera } from './camera'
import { PointRenderable, MeshRenderable, Renderable } from './renderable'
import { Vec3, Mat4 } from 'mol-math/linear-algebra'
let _renderObjectId = 0;
function getNextId() {
return _renderObjectId++ % 0x7FFFFFFF;
}
export interface RenderObject {
id: number
type: 'mesh' | 'point'
data: any
elements: any
uniforms: any
}
export function createRenderObject(type: 'mesh' | 'point', data: any, elements?: any, uniforms?: any) {
return { id: getNextId(), type, data, elements, uniforms }
}
export interface Renderer {
add: (o: RenderObject) => void
remove: (o: RenderObject) => void
draw: () => void
frame: () => void
}
export function createRenderable(regl: REGL.Regl, o: RenderObject) {
switch (o.type) {
case 'mesh': return MeshRenderable.create(regl, o.data, o.uniforms || {}, o.elements)
case 'point': return PointRenderable.create(regl, o.data)
}
}
export function createRenderer(container: HTMLDivElement): Renderer {
const renderableList: Renderable<any>[] = []
const objectIdRenderableMap: { [k: number]: Renderable<any> } = {}
const regl = glContext.create({
container,
extensions: [
'OES_texture_float',
'OES_texture_float_linear',
'OES_element_index_uint',
// 'EXT_disjoint_timer_query',
'EXT_blend_minmax',
'ANGLE_instanced_arrays'
],
// profile: true
})
const camera = Camera.create(regl, container, {
center: Vec3.create(0, 0, 0),
near: 0.01,
far: 1000
})
const baseContext = regl({
context: {
model: Mat4.identity(),
transform: Mat4.setTranslation(Mat4.identity(), Vec3.create(6, 0, 0))
},
uniforms: {
model: regl.context('model' as any),
transform: regl.context('transform' as any),
'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
}
})
const draw = () => {
camera.update((state: any) => {
if (!camera.isDirty()) return;
baseContext(() => {
// console.log(ctx)
regl.clear({color: [0, 0, 0, 1]})
// TODO painters sort, filter visible, filter picking, visibility culling?
renderableList.forEach(r => {
r.draw()
})
})
}, undefined)
}
return {
add: (o: RenderObject) => {
const renderable = createRenderable(regl, o)
renderableList.push(renderable)
objectIdRenderableMap[o.id] = renderable
},
remove: (o: RenderObject) => {
if (o.id in objectIdRenderableMap) {
// TODO
// objectIdRenderableMap[o.id].destroy()
delete objectIdRenderableMap[o.id]
}
},
draw,
frame: () => {
regl.frame((ctx) => draw())
}
}
}
\ No newline at end of file
......@@ -11,3 +11,17 @@ export function calculateTextureInfo (n: number, itemSize: number) {
const height = width > 0 ? Math.ceil(n * itemSize / width) : 0
return { width, height, length: width * height * itemSize }
}
export interface ColorTexture extends Uint8Array {
width: number,
height: number
}
export function createColorTexture (n: number): ColorTexture {
const colorTexInfo = calculateTextureInfo(n, 3)
const colorTexture = new Uint8Array(colorTexInfo.length)
return Object.assign(colorTexture, {
width: colorTexInfo.width,
height: colorTexInfo.height
})
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment