Browse Source

parser is working + try to get mesh/shape

MarcoSchaeferT 6 years ago
parent
commit
a80088ec0f

+ 5 - 2
src/mol-io/reader/ply/parse_data/data-model.ts

@@ -24,11 +24,14 @@ export interface ply_form {
     readonly initialHead: ReadonlyArray<string>,
     readonly propertyNames: ReadonlyArray<string>,
     readonly properties: number[],
+    readonly vertices: number[],
+    readonly colors: number[],
+    readonly normals: number[],
     readonly  faces: number[],
 }
 
-export function PlyStructure(vertexCount: number, faceCount: number, propertyCount: number, initialHead: string[], propertyNames: string[],  properties: number[], faces: number[]): ply_form {
-    return {vertexCount, faceCount, propertyCount, initialHead: [...initialHead], propertyNames: [...propertyNames], properties: [...properties], faces: [...faces]};
+export function PlyStructure(vertexCount: number, faceCount: number, propertyCount: number, initialHead: string[], propertyNames: string[],  properties: number[],  vertices: number[],  colors: number[],  normals: number[], faces: number[]): ply_form {
+    return {vertexCount, faceCount, propertyCount, initialHead: [...initialHead], propertyNames: [...propertyNames], properties: [...properties], vertices: [...vertices], colors: [...colors], normals: [...normals], faces: [...faces]};
 }
 
 export type PlyColumns = { [name: string]: PlyColumn }

+ 0 - 9
src/mol-io/reader/ply/parse_data/field.ts

@@ -1,9 +0,0 @@
-/**
- * Copyright (c) 2017 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- */
-
-import Field from '../../cif/text/field'
-
-export default Field

+ 36 - 5
src/mol-io/reader/ply/parse_data/ply_parser.ts

@@ -9,8 +9,15 @@ import { Tokens, TokenBuilder, Tokenizer } from '../../common/text/tokenizer'
 import * as Data from './data-model'
 
 import Result from '../../result'
-import { Task, RuntimeContext, chunkedSubtask, } from 'mol-task'
-
+import {Task, RuntimeContext, chunkedSubtask, Progress,} from 'mol-task'
+import * as plyToShape from 'mol-model/shape/formarts/ply/plyData_to_shape'
+import {MyData} from 'mol-model/shape/formarts/ply/plyData_to_shape';
+import {Mesh} from '../../../../mol-geo/geometry/mesh/mesh';
+import {ParamDefinition} from '../../../../mol-util/param-definition';
+import Color = ParamDefinition.Color;
+import {ColorNames} from '../../../../mol-util/color/tables';
+import {ShapeRepresentation} from '../../../../mol-repr/shape/representation';
+//import {init2} from '../../../../tests/browser/render-shape';
 
 
 
@@ -46,6 +53,9 @@ interface State {
 
     initialHead: string[],
     properties: number[],
+    vertices: number[],
+    colors: number[],
+    normals: number[],
     faces: number[],
     propertyNames: string[],
     check: string[],
@@ -80,6 +90,9 @@ function State(data: string, runtimeCtx: RuntimeContext, opts: PlyOptions): Stat
 
         initialHead: [],
         properties: [],
+        vertices: [],
+        colors: [],
+        normals:[],
         faces: [],
         propertyNames: [],
         check: [],
@@ -192,6 +205,15 @@ function moveNextInternal(state: State) {
             {
                 if(state.currentVertex < state.vertexCount){
                     state.properties[state.currentVertex * state.propertyCount + state.currentProperty] = Number(Tokenizer.getTokenString(state.tokenizer));
+                    if(state.currentProperty < 3){
+                        state.vertices[state.currentVertex * 3 + state.currentProperty] = Number(Tokenizer.getTokenString(state.tokenizer));
+                    }
+                    if(state.currentProperty >= 3 && state.currentProperty <6){
+                        state.colors[state.currentVertex * 3 + state.currentProperty-3] = Number(Tokenizer.getTokenString(state.tokenizer));
+                    }
+                    if(state.currentProperty >= 6 && state.currentProperty <9){
+                        state.normals[state.currentVertex * 3 + state.currentProperty-6] = Number(Tokenizer.getTokenString(state.tokenizer));
+                    }
                     state.currentProperty++;
                     if(state.currentProperty === state.propertyCount){
                         state.currentProperty = 0;
@@ -287,16 +309,25 @@ async function handleRecords(state: State): Promise<Data.ply_form> {
     }
     await readRecordsChunks(state)
 
-    return Data.PlyStructure(state.vertexCount, state.faceCount, state.propertyCount, state.initialHead, state.propertyNames, state.properties, state.faces)
+    return Data.PlyStructure(state.vertexCount, state.faceCount, state.propertyCount, state.initialHead, state.propertyNames, state.properties, state.vertices, state.colors, state.normals, state.faces)
 }
 
 async function parseInternal(data: string, ctx: RuntimeContext, opts: PlyOptions): Promise<Result<Data.PlyFile>> {
     const state = State(data, ctx, opts);
 
     ctx.update({ message: 'Parsing...', current: 0, max: data.length });
-    const table = await handleRecords(state)
-    const result = Data.PlyFile(table)
+    const PLYdata = await handleRecords(state)
+    const result = Data.PlyFile(PLYdata)
     console.log(result);
+
+   // let Data_for_Shape = plyToShape.collectData_for_Shape(table, datas);
+    //console.log(plyToShape.getShape(state.runtimeCtx, table));
+    let shape  = plyToShape.init_ren(PLYdata);
+    console.log("shape"+shape);
+    const script = document.createElement('script');
+    script.src = "../../build/src/mol-model/shape/formarts/ply/plyData_to_shape.js";
+    document.body.appendChild(script);
+
     return Result.success(result);
 }
 

+ 143 - 0
src/mol-model/shape/formarts/ply/plyData_to_shape.ts

@@ -0,0 +1,143 @@
+import {ply_form} from '../../../../mol-io/reader/ply/parse_data/data-model';
+import {MyData} from '../../../../../build/src/mol-model/shape/formarts/ply/plyData_to_shape';
+import {Progress, RuntimeContext} from 'mol-task';
+import {Mesh} from '../../../../mol-geo/geometry/mesh/mesh';
+import {MeshBuilder} from '../../../../mol-geo/geometry/mesh/mesh-builder';
+import {Mat4, Vec3} from '../../../../mol-math/linear-algebra/3d';
+import {Sphere} from '../../../../mol-geo/primitive/sphere';
+import {Shape} from '../../shape';
+import {Color} from '../../../../mol-util/color';
+import {Canvas3D} from '../../../../mol-canvas3d/canvas3d';
+import {labelFirst} from '../../../../mol-theme/label';
+import {ColorNames} from '../../../../mol-util/color/tables';
+import {ShapeRepresentation} from '../../../../mol-repr/shape/representation';
+
+
+const parent = document.getElementById('app')!
+parent.style.width = '100%'
+parent.style.height = '100%'
+
+const canvas = document.createElement('canvas')
+canvas.style.width = '100%'
+canvas.style.height = '100%'
+parent.appendChild(canvas)
+
+const info = document.createElement('div')
+info.style.position = 'absolute'
+info.style.fontFamily = 'sans-serif'
+info.style.fontSize = '24pt'
+info.style.bottom = '20px'
+info.style.right = '20px'
+info.style.color = 'white'
+parent.appendChild(info)
+
+const canvas3d = Canvas3D.create(canvas, parent)
+canvas3d.animate()
+canvas3d.input.move.subscribe(async ({x, y}) => {
+    const pickingId = await canvas3d.identify(x, y)
+    let label = ''
+    if (pickingId) {
+        const { loci } = canvas3d.getLoci(pickingId)
+        label = labelFirst(loci)
+    }
+    info.innerText = label
+})
+
+
+
+
+export interface MyData {
+    centers: number[],
+    colors: string[],
+    labels: string[],
+    transforms: number[]
+}
+
+let data:MyData = {
+    centers: [],
+    colors: [],
+    labels: [],
+    transforms:[]
+}
+
+
+function componentToHex(c) {
+    let hex = c.toString(16);
+    return hex.length == 1 ? "0" + hex : hex;
+}
+
+function rgbToHex(r, g, b) {
+    return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);
+}
+
+ function collectData_for_Shape(parsedData: ply_form):{centers: number[], colors: string[], labels: string[], transforms: number[]}{
+    // parsedData.data.PLY_File. to access So.format.Ply
+
+    data.centers = parsedData.vertices;
+    let hexColor;
+
+    for(let i=0; i<parsedData.vertexCount; i++){
+        hexColor = rgbToHex(parsedData.colors[i*3+0],parsedData.colors[i*3+1],parsedData.colors[i*3+2]);
+        data.colors[i] = hexColor;
+        data.labels[i] = '';
+        data.transforms[i] = 0;
+    }
+    console.log(data);
+    return data;
+}
+
+
+
+
+ async function getSphereMesh(ctx: RuntimeContext, centers: number[], mesh?: Mesh) {
+    const builderState = MeshBuilder.createState(centers.length * 128, centers.length * 128 / 2, mesh)
+    const t = Mat4.identity()
+    const v = Vec3.zero()
+    const sphere = Sphere(4)
+    builderState.currentGroup = 0
+    for (let i = 0, il = centers.length / 3; i < il; ++i) {
+        // for production, calls to update should be guarded by `if (ctx.shouldUpdate)`
+        await ctx.update({ current: i, max: il, message: `adding sphere ${i}` })
+        builderState.currentGroup = i
+        Mat4.setTranslation(t, Vec3.fromArray(v, centers, i * 3))
+        MeshBuilder.addPrimitive(builderState, t, sphere)
+    }
+    let a = MeshBuilder.getMesh(builderState);
+    //console.log(a);
+    return a
+}
+
+
+export async function getShape(ctx: RuntimeContext, parsedData: ply_form, props: {}, shape?: Shape<Mesh>) {
+    let data:MyData;
+    data = collectData_for_Shape(parsedData)
+    await ctx.update('async creation of shape from  myData')
+    const { centers , colors, labels} = data
+    const mesh = await getSphereMesh(ctx, centers, shape && shape.geometry)
+    const groupCount = centers.length / 3
+    return shape || Shape.create(
+        'test', mesh,
+        (groupId: number) => Color(Number(colors[groupId])), // color: per group, same for instances
+        () => 1, // size: constant
+        (groupId: number, instanceId: number) => labels[instanceId * groupCount + groupId] // label: per group and instance
+    )
+}
+
+const repr = ShapeRepresentation(getShape, Mesh.Utils)
+
+export async function init_ren(myData : ply_form) {
+    // Create shape from myData and add to canvas3d
+    await repr.createOrUpdate({}, myData).run((p: Progress) => console.log(Progress.format(p)))
+    canvas3d.add(repr)
+    canvas3d.resetCamera()
+
+    // Change color after 1s
+    setTimeout(async () => {
+        myData.colors[0] = ColorNames.darkmagenta
+        // Calling `createOrUpdate` with `data` will trigger color and transform update
+        await repr.createOrUpdate({}, myData).run()
+    }, 1000)
+}
+
+
+

+ 7 - 5
src/mol-plugin/state/actions/basic.ts

@@ -14,7 +14,9 @@ import { PluginStateObject } from '../objects';
 import { StateTransforms } from '../transforms';
 import { Download } from '../transforms/data';
 import { StructureRepresentation3DHelpers } from '../transforms/representation';
-import * as data_functions from "mol-io/reader/ply//read_data/data"
+import * as data_functions from 'mol-io/reader/ply/read_data/data'
+
+
 
 // TODO: "structure parser provider"
 
@@ -86,6 +88,7 @@ export const OpenStructure = StateAction.build({
     return state.update(createStructureTree(ctx, data, false));
 });
 
+
 export const PLYtest = StateAction.build({
     display: { name: 'PLY Test', description: 'nothing ply' },
     from: PluginStateObject.Root,
@@ -93,13 +96,12 @@ export const PLYtest = StateAction.build({
 })(({ params, state }, ctx: PluginContext) => {
     const b = state.build();
     const data = b.toRoot().apply(data_functions.ReadFile_ascii, { file: params.file, isBinary: false });
-    return state.update(getPLYdata(ctx, data));
+    let tmp = state.update(getPLYdata(ctx, data));
+    return tmp ;
 });
 
 function getPLYdata(ctx: PluginContext, b: StateTreeBuilder.To<PluginStateObject.Data.String>, ): StateTree {
-    let root = b
-        .apply(data_functions.ParsePLY);
-    console.log(data_functions.ParsePLY);
+    let root = b.apply(data_functions.ParsePLY);
 
     return root.getTree();
 }

+ 27 - 24
src/tests/browser/index.html

@@ -1,39 +1,42 @@
 <!DOCTYPE html>
 <html lang="en">
-    <head>
+<head>
         <meta charset="utf-8" />
         <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
         <title>Mol* Browser Test</title>
         <style>
-            * {
-                margin: 0;
-                padding: 0;
-                box-sizing: border-box;
-            }
-            html, body {
-                width: 100%;
-                height: 100%;
-                overflow: hidden;
-            }
+                * {
+                        margin: 0;
+                        padding: 0;
+                        box-sizing: border-box;
+                }
+                html, body {
+                        width: 100%;
+                        height: 100%;
+                        overflow: hidden;
+                }
         </style>
-    </head>
-    <body>
-        <div id="app"></div>
-        <script type="text/javascript">
-            function urlQueryParameter (id) {
+</head>
+<body>
+<div id="app"></div>
+<script type="text/javascript">
+        function urlQueryParameter (id) {
                 if (typeof window === 'undefined') return undefined
                 const a = new RegExp(`${id}=([^&#=]*)`)
                 const m = a.exec(window.location.search)
                 return m ? decodeURIComponent(m[1]) : undefined
-            }
-
-            const name = urlQueryParameter('name')
-            if (name) {
+        }
+        const name = urlQueryParameter('name')
+        if (name) {
                 const script = document.createElement('script')
                 script.src = name + '.js'
                 document.body.appendChild(script)
-            }
-        </script>
-        <script type="text/javascript" src="./render-shape.js"></script>
-    </body>
+        }
+</script>
+<script type="text/javascript" >
+        const script = document.createElement('script');
+        script.src = "render-shape.js";
+        document.body.appendChild(script);
+</script>
+</body>
 </html>

+ 1 - 1
src/tests/browser/render-shape.ts

@@ -18,6 +18,7 @@ import { RuntimeContext, Progress } from 'mol-task';
 
 
 
+
 const parent = document.getElementById('app')!
 parent.style.width = '100%'
 parent.style.height = '100%'
@@ -101,7 +102,6 @@ const repr = ShapeRepresentation(getShape, Mesh.Utils)
 export async function init() {
     // Create shape from myData and add to canvas3d
     await repr.createOrUpdate({}, myData).run((p: Progress) => console.log(Progress.format(p)))
-    console.log(repr)
     canvas3d.add(repr)
     canvas3d.resetCamera()