Browse Source

address @arose's comments

Sukolsak Sakshuwong 3 years ago
parent
commit
7542ead360

+ 2 - 2
src/extensions/geo-export/controls.ts

@@ -32,8 +32,8 @@ export class GeometryControls extends PluginComponent {
         return `${idString || 'molstar-model'}`;
     }
 
-    exportGeometries() {
-        const task = Task.create('Export Geometries', async ctx => {
+    exportGeometry() {
+        const task = Task.create('Export Geometry', async ctx => {
             try {
                 const renderObjects = this.plugin.canvas3d?.getRenderObjects()!;
                 const filename = this.getFilename();

+ 7 - 8
src/extensions/geo-export/glb-exporter.ts

@@ -5,6 +5,7 @@
  */
 
 import { BaseValues } from '../../mol-gl/renderable/schema';
+import { asciiWrite } from '../../mol-io/common/ascii';
 import { IsNativeEndianLittle, flipByteOrder } from '../../mol-io/common/binary';
 import { Vec3, Mat3, Mat4 } from '../../mol-math/linear-algebra';
 import { RuntimeContext } from '../../mol-task';
@@ -49,11 +50,11 @@ export class GlbExporter extends MeshExporter<GlbData> {
         return [ min, max ];
     }
 
-    async addMeshWithColors(vertices: Float32Array, normals: Float32Array, indices: Uint32Array | undefined, groups: Float32Array | Uint8Array, vertexCount: number, drawCount: number, values: BaseValues, instanceIndex: number, geoTexture: boolean, ctx: RuntimeContext) {
+    async addMeshWithColors(vertices: Float32Array, normals: Float32Array, indices: Uint32Array | undefined, groups: Float32Array | Uint8Array, vertexCount: number, drawCount: number, values: BaseValues, instanceIndex: number, isGeoTexture: boolean, ctx: RuntimeContext) {
         const t = Mat4();
         const n = Mat3();
         const tmpV = Vec3();
-        const stride = geoTexture ? 4 : 3;
+        const stride = isGeoTexture ? 4 : 3;
 
         const colorType = values.dColorType.ref.value;
         const tColor = values.tColor.ref.value.array;
@@ -99,13 +100,13 @@ export class GlbExporter extends MeshExporter<GlbData> {
                     color = Color.fromArray(tColor, instanceIndex * 3);
                     break;
                 case 'group': {
-                    const group = geoTexture ? GlbExporter.getGroup(groups, i) : groups[i];
+                    const group = isGeoTexture ? GlbExporter.getGroup(groups, i) : groups[i];
                     color = Color.fromArray(tColor, group * 3);
                     break;
                 }
                 case 'groupInstance': {
                     const groupCount = values.uGroupCount.ref.value;
-                    const group = geoTexture ? GlbExporter.getGroup(groups, i) : groups[i];
+                    const group = isGeoTexture ? GlbExporter.getGroup(groups, i) : groups[i];
                     color = Color.fromArray(tColor, (instanceIndex * groupCount + group) * 3);
                     break;
                 }
@@ -122,7 +123,7 @@ export class GlbExporter extends MeshExporter<GlbData> {
         }
 
         // face
-        if (geoTexture) {
+        if (isGeoTexture) {
             indexArray = new Uint32Array(drawCount);
             fillSerial(indexArray);
         } else {
@@ -277,9 +278,7 @@ export class GlbExporter extends MeshExporter<GlbData> {
         };
         const jsonString = JSON.stringify(gltf);
         const jsonBuffer = new Uint8Array(jsonString.length);
-        for (let i = 0, il = jsonString.length; i < il; ++i) {
-            jsonBuffer[i] = jsonString.charCodeAt(i);
-        }
+        asciiWrite(jsonBuffer, jsonString);
 
         const [ jsonChunk, jsonChunkLength ] = createChunk(0x4E4F534A, [jsonBuffer.buffer], jsonBuffer.length, 0x20);
         const [ binaryChunk, binaryChunkLength ] = createChunk(0x004E4942, this.binaryBuffer, binaryBufferLength, 0x00);

+ 6 - 5
src/extensions/geo-export/mesh-exporter.ts

@@ -17,6 +17,7 @@ import { WebGLContext } from '../../mol-gl/webgl/context';
 import { MeshBuilder } from '../../mol-geo/geometry/mesh/mesh-builder';
 import { addSphere } from '../../mol-geo/geometry/mesh/builder/sphere';
 import { addCylinder } from '../../mol-geo/geometry/mesh/builder/cylinder';
+import { sizeDataFactor } from '../../mol-geo/geometry/size-data';
 import { Vec3 } from '../../mol-math/linear-algebra';
 import { RuntimeContext } from '../../mol-task';
 import { decodeFloatRGB } from '../../mol-util/float-packing';
@@ -32,7 +33,7 @@ export abstract class MeshExporter<D extends RenderObjectExportData> implements
         const r = tSize.array[i * 3];
         const g = tSize.array[i * 3 + 1];
         const b = tSize.array[i * 3 + 2];
-        return decodeFloatRGB(r, g, b);
+        return decodeFloatRGB(r, g, b) / sizeDataFactor;
     }
 
     private static getSize(values: BaseValues & SizeValues, instanceIndex: number, group: number): number {
@@ -43,14 +44,14 @@ export abstract class MeshExporter<D extends RenderObjectExportData> implements
                 size = values.uSize.ref.value;
                 break;
             case 'instance':
-                size = MeshExporter.getSizeFromTexture(tSize, instanceIndex) / 100;
+                size = MeshExporter.getSizeFromTexture(tSize, instanceIndex);
                 break;
             case 'group':
-                size = MeshExporter.getSizeFromTexture(tSize, group) / 100;
+                size = MeshExporter.getSizeFromTexture(tSize, group);
                 break;
             case 'groupInstance':
                 const groupCount = values.uGroupCount.ref.value;
-                size = MeshExporter.getSizeFromTexture(tSize, instanceIndex * groupCount + group) / 100;
+                size = MeshExporter.getSizeFromTexture(tSize, instanceIndex * groupCount + group);
                 break;
         }
         return size * values.uSizeFactor.ref.value;
@@ -67,7 +68,7 @@ export abstract class MeshExporter<D extends RenderObjectExportData> implements
         return decodeFloatRGB(r, g, b);
     }
 
-    protected abstract addMeshWithColors(vertices: Float32Array, normals: Float32Array, indices: Uint32Array | undefined, groups: Float32Array | Uint8Array, vertexCount: number, drawCount: number, values: BaseValues, instanceIndex: number, geoTexture: boolean, ctx: RuntimeContext): void;
+    protected abstract addMeshWithColors(vertices: Float32Array, normals: Float32Array, indices: Uint32Array | undefined, groups: Float32Array | Uint8Array, vertexCount: number, drawCount: number, values: BaseValues, instanceIndex: number, isGeoTexture: boolean, ctx: RuntimeContext): void;
 
     private async addMesh(values: MeshValues, ctx: RuntimeContext) {
         const aPosition = values.aPosition.ref.value;

+ 8 - 12
src/extensions/geo-export/obj-exporter.ts

@@ -5,6 +5,7 @@
  */
 
 import { BaseValues } from '../../mol-gl/renderable/schema';
+import { asciiWrite } from '../../mol-io/common/ascii';
 import { Vec3, Mat3, Mat4 } from '../../mol-math/linear-algebra';
 import { RuntimeContext } from '../../mol-task';
 import { StringBuilder } from '../../mol-util';
@@ -66,12 +67,12 @@ export class ObjExporter extends MeshExporter<ObjData> {
         }
     }
 
-    protected async addMeshWithColors(vertices: Float32Array, normals: Float32Array, indices: Uint32Array | undefined, groups: Float32Array | Uint8Array, vertexCount: number, drawCount: number, values: BaseValues, instanceIndex: number, geoTexture: boolean, ctx: RuntimeContext) {
+    protected async addMeshWithColors(vertices: Float32Array, normals: Float32Array, indices: Uint32Array | undefined, groups: Float32Array | Uint8Array, vertexCount: number, drawCount: number, values: BaseValues, instanceIndex: number, isGeoTexture: boolean, ctx: RuntimeContext) {
         const obj = this.obj;
         const t = Mat4();
         const n = Mat3();
         const tmpV = Vec3();
-        const stride = geoTexture ? 4 : 3;
+        const stride = isGeoTexture ? 4 : 3;
 
         const colorType = values.dColorType.ref.value;
         const tColor = values.tColor.ref.value.array;
@@ -122,13 +123,13 @@ export class ObjExporter extends MeshExporter<ObjData> {
                     color = Color.fromArray(tColor, instanceIndex * 3);
                     break;
                 case 'group': {
-                    const group = geoTexture ? ObjExporter.getGroup(groups, i) : groups[indices![i]];
+                    const group = isGeoTexture ? ObjExporter.getGroup(groups, i) : groups[indices![i]];
                     color = Color.fromArray(tColor, group * 3);
                     break;
                 }
                 case 'groupInstance': {
                     const groupCount = values.uGroupCount.ref.value;
-                    const group = geoTexture ? ObjExporter.getGroup(groups, i) : groups[indices![i]];
+                    const group = isGeoTexture ? ObjExporter.getGroup(groups, i) : groups[indices![i]];
                     color = Color.fromArray(tColor, (instanceIndex * groupCount + group) * 3);
                     break;
                 }
@@ -142,9 +143,9 @@ export class ObjExporter extends MeshExporter<ObjData> {
             }
             this.updateMaterial(color, uAlpha);
 
-            const v1 = this.vertexOffset + (geoTexture ? i : indices![i]) + 1;
-            const v2 = this.vertexOffset + (geoTexture ? i + 1 : indices![i + 1]) + 1;
-            const v3 = this.vertexOffset + (geoTexture ? i + 2 : indices![i + 2]) + 1;
+            const v1 = this.vertexOffset + (isGeoTexture ? i : indices![i]) + 1;
+            const v2 = this.vertexOffset + (isGeoTexture ? i + 1 : indices![i + 1]) + 1;
+            const v3 = this.vertexOffset + (isGeoTexture ? i + 2 : indices![i + 2]) + 1;
             StringBuilder.writeSafe(obj, 'f ');
             StringBuilder.writeInteger(obj, v1);
             StringBuilder.writeSafe(obj, '//');
@@ -170,11 +171,6 @@ export class ObjExporter extends MeshExporter<ObjData> {
 
     async getBlob(ctx: RuntimeContext) {
         const { obj, mtl } = this.getData();
-        const asciiWrite = (data: Uint8Array, str: string) => {
-            for (let i = 0, il = str.length; i < il; ++i) {
-                data[i] = str.charCodeAt(i);
-            }
-        };
         const objData = new Uint8Array(obj.length);
         asciiWrite(objData, obj);
         const mtlData = new Uint8Array(mtl.length);

+ 11 - 5
src/extensions/geo-export/stl-exporter.ts

@@ -5,7 +5,9 @@
  */
 
 import { BaseValues } from '../../mol-gl/renderable/schema';
+import { asciiWrite } from '../../mol-io/common/ascii';
 import { Vec3, Mat4 } from '../../mol-math/linear-algebra';
+import { PLUGIN_VERSION } from '../../mol-plugin/version';
 import { RuntimeContext } from '../../mol-task';
 import { MeshExporter } from './mesh-exporter';
 
@@ -15,6 +17,8 @@ const v3transformMat4 = Vec3.transformMat4;
 const v3triangleNormal = Vec3.triangleNormal;
 const v3toArray = Vec3.toArray;
 
+// https://www.fabbers.com/tech/STL_Format
+
 export type StlData = {
     stl: Uint8Array
 }
@@ -24,14 +28,14 @@ export class StlExporter extends MeshExporter<StlData> {
     private triangleBuffers: ArrayBuffer[] = [];
     private triangleCount = 0;
 
-    async addMeshWithColors(vertices: Float32Array, normals: Float32Array, indices: Uint32Array | undefined, groups: Float32Array | Uint8Array, vertexCount: number, drawCount: number, values: BaseValues, instanceIndex: number, geoTexture: boolean, ctx: RuntimeContext) {
+    async addMeshWithColors(vertices: Float32Array, normals: Float32Array, indices: Uint32Array | undefined, groups: Float32Array | Uint8Array, vertexCount: number, drawCount: number, values: BaseValues, instanceIndex: number, isGeoTexture: boolean, ctx: RuntimeContext) {
         const t = Mat4();
         const tmpV = Vec3();
         const v1 = Vec3();
         const v2 = Vec3();
         const v3 = Vec3();
         const n = Vec3();
-        const stride = geoTexture ? 4 : 3;
+        const stride = isGeoTexture ? 4 : 3;
 
         const aTransform = values.aTransform.ref.value;
         Mat4.fromArray(t, aTransform, instanceIndex * 16);
@@ -53,9 +57,9 @@ export class StlExporter extends MeshExporter<StlData> {
         for (let i = 0; i < drawCount; i += 3) {
             if (i % 3000 === 0 && ctx.shouldUpdate) await ctx.update({ current: currentProgress + vertexCount + i });
 
-            v3fromArray(v1, vertexArray, (geoTexture ? i : indices![i]) * 3);
-            v3fromArray(v2, vertexArray, (geoTexture ? i + 1 : indices![i + 1]) * 3);
-            v3fromArray(v3, vertexArray, (geoTexture ? i + 2 : indices![i + 2]) * 3);
+            v3fromArray(v1, vertexArray, (isGeoTexture ? i : indices![i]) * 3);
+            v3fromArray(v2, vertexArray, (isGeoTexture ? i + 1 : indices![i + 1]) * 3);
+            v3fromArray(v3, vertexArray, (isGeoTexture ? i + 2 : indices![i + 2]) * 3);
             v3triangleNormal(n, v1, v2, v3);
 
             const byteOffset = 50 * i;
@@ -83,6 +87,8 @@ export class StlExporter extends MeshExporter<StlData> {
     getData() {
         const stl = new Uint8Array(84 + 50 * this.triangleCount);
 
+        asciiWrite(stl, `Exported from Mol* ${PLUGIN_VERSION}`);
+
         const dataView = new DataView(stl.buffer);
         dataView.setUint32(80, this.triangleCount, true);
 

+ 2 - 2
src/extensions/geo-export/ui.tsx

@@ -25,7 +25,7 @@ export class GeometryExporterUI extends CollapsableControls<{}, State> {
 
     protected defaultState(): State & CollapsableState {
         return {
-            header: 'Export Geometries',
+            header: 'Export Geometry',
             isCollapsed: true,
             brand: { accent: 'cyan', svg: CubeSendSvg }
         };
@@ -67,7 +67,7 @@ export class GeometryExporterUI extends CollapsableControls<{}, State> {
     save = async () => {
         try {
             this.setState({ busy: true });
-            const data = await this.controls.exportGeometries();
+            const data = await this.controls.exportGeometry();
             this.setState({ busy: false });
 
             download(data.blob, data.filename);

+ 5 - 5
src/mol-geo/geometry/size-data.ts

@@ -31,7 +31,7 @@ export function createSizes(locationIt: LocationIterator, sizeTheme: SizeTheme<a
     }
 }
 
-const sizeFactor = 100; // NOTE same factor is set in shaders
+export const sizeDataFactor = 100; // NOTE same factor is set in shaders
 
 export function getMaxSize(sizeData: SizeData): number {
     const type = sizeData.dSizeType.ref.value as SizeType;
@@ -47,7 +47,7 @@ export function getMaxSize(sizeData: SizeData): number {
                 const value = decodeFloatRGB(array[i], array[i + 1], array[i + 2]);
                 if (maxSize < value) maxSize = value;
             }
-            return maxSize / sizeFactor;
+            return maxSize / sizeDataFactor;
     }
 }
 
@@ -103,7 +103,7 @@ export function createInstanceSize(locationIt: LocationIterator, sizeFn: Locatio
     locationIt.reset();
     while (locationIt.hasNext && !locationIt.isNextNewInstance) {
         const v = locationIt.move();
-        encodeFloatRGBtoArray(sizeFn(v.location) * sizeFactor, sizes.array, v.instanceIndex * 3);
+        encodeFloatRGBtoArray(sizeFn(v.location) * sizeDataFactor, sizes.array, v.instanceIndex * 3);
         locationIt.skipInstance();
     }
     return createTextureSize(sizes, 'instance', sizeData);
@@ -116,7 +116,7 @@ export function createGroupSize(locationIt: LocationIterator, sizeFn: LocationSi
     locationIt.reset();
     while (locationIt.hasNext && !locationIt.isNextNewInstance) {
         const v = locationIt.move();
-        encodeFloatRGBtoArray(sizeFn(v.location) * sizeFactor, sizes.array, v.groupIndex * 3);
+        encodeFloatRGBtoArray(sizeFn(v.location) * sizeDataFactor, sizes.array, v.groupIndex * 3);
     }
     return createTextureSize(sizes, 'group', sizeData);
 }
@@ -129,7 +129,7 @@ export function createGroupInstanceSize(locationIt: LocationIterator, sizeFn: Lo
     locationIt.reset();
     while (locationIt.hasNext) {
         const v = locationIt.move();
-        encodeFloatRGBtoArray(sizeFn(v.location) * sizeFactor, sizes.array, v.index * 3);
+        encodeFloatRGBtoArray(sizeFn(v.location) * sizeDataFactor, sizes.array, v.index * 3);
     }
     return createTextureSize(sizes, 'groupInstance', sizeData);
 }

+ 11 - 0
src/mol-io/common/ascii.ts

@@ -0,0 +1,11 @@
+/**
+ * Copyright (c) 2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Sukolsak Sakshuwong <sukolsak@stanford.edu>
+ */
+
+export function asciiWrite(data: Uint8Array, str: string) {
+    for (let i = 0, il = str.length; i < il; ++i) {
+        data[i] = str.charCodeAt(i);
+    }
+}