Quellcode durchsuchen

Merge pull request #212 from sukolsak/center-export

Geometry export: center exported models
David Sehnal vor 3 Jahren
Ursprung
Commit
eb629ef337

+ 8 - 6
src/extensions/geo-export/controls.ts

@@ -5,6 +5,7 @@
  */
 
 import { getStyle } from '../../mol-gl/renderer';
+import { Box3D } from '../../mol-math/geometry';
 import { PluginComponent } from '../../mol-plugin-state/component';
 import { PluginContext } from '../../mol-plugin/context';
 import { Task } from '../../mol-task';
@@ -43,17 +44,18 @@ export class GeometryControls extends PluginComponent {
                 const renderObjects = this.plugin.canvas3d?.getRenderObjects()!;
                 const filename = this.getFilename();
 
-                let renderObjectExporter: ObjExporter | GlbExporter | StlExporter;
+                const boundingBox = Box3D.fromSphere3D(Box3D(), this.plugin.canvas3d?.boundingSphereVisible!);
+                let renderObjectExporter: GlbExporter | ObjExporter | StlExporter;
                 switch (this.behaviors.params.value.format) {
-                    case 'obj':
-                        renderObjectExporter = new ObjExporter(filename);
-                        break;
                     case 'glb':
                         const style = getStyle(this.plugin.canvas3d?.props.renderer.style!);
-                        renderObjectExporter = new GlbExporter(style);
+                        renderObjectExporter = new GlbExporter(style, boundingBox);
+                        break;
+                    case 'obj':
+                        renderObjectExporter = new ObjExporter(filename, boundingBox);
                         break;
                     case 'stl':
-                        renderObjectExporter = new StlExporter();
+                        renderObjectExporter = new StlExporter(boundingBox);
                         break;
                     default: throw new Error('Unsupported format.');
                 }

+ 11 - 4
src/extensions/geo-export/glb-exporter.ts

@@ -8,6 +8,7 @@ import { BaseValues } from '../../mol-gl/renderable/schema';
 import { Style } from '../../mol-gl/renderer';
 import { asciiWrite } from '../../mol-io/common/ascii';
 import { IsNativeEndianLittle, flipByteOrder } from '../../mol-io/common/binary';
+import { Box3D } from '../../mol-math/geometry';
 import { Vec3, Mat4 } from '../../mol-math/linear-algebra';
 import { PLUGIN_VERSION } from '../../mol-plugin/version';
 import { RuntimeContext } from '../../mol-task';
@@ -41,6 +42,7 @@ export class GlbExporter extends MeshExporter<GlbData> {
     private bufferViews: Record<string, any>[] = [];
     private binaryBuffer: ArrayBuffer[] = [];
     private byteOffset = 0;
+    private centerTransform: Mat4;
 
     private static vec3MinMax(a: NumberArray) {
         const min: number[] = [Infinity, Infinity, Infinity];
@@ -252,11 +254,12 @@ export class GlbExporter extends MeshExporter<GlbData> {
             }
 
             // node
+            Mat4.fromArray(t, aTransform, instanceIndex * 16);
+            Mat4.mul(t, this.centerTransform, t);
             const node: Record<string, any> = {
-                mesh: meshIndex!
+                mesh: meshIndex!,
+                matrix: t.slice()
             };
-            Mat4.fromArray(t, aTransform, instanceIndex * 16);
-            if (!Mat4.isIdentity(t)) node.matrix = t.slice();
             this.nodes.push(node);
         }
     }
@@ -334,7 +337,11 @@ export class GlbExporter extends MeshExporter<GlbData> {
         return new Blob([this.getData().glb], { type: 'model/gltf-binary' });
     }
 
-    constructor(private style: Style) {
+    constructor(private style: Style, boundingBox: Box3D) {
         super();
+        const tmpV = Vec3();
+        Vec3.add(tmpV, boundingBox.min, boundingBox.max);
+        Vec3.scale(tmpV, tmpV, -0.5);
+        this.centerTransform = Mat4.fromTranslation(Mat4(), tmpV);
     }
 }

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

@@ -6,6 +6,7 @@
 
 import { sort, arraySwap } from '../../mol-data/util';
 import { asciiWrite } from '../../mol-io/common/ascii';
+import { Box3D } from '../../mol-math/geometry';
 import { Vec3, Mat3, Mat4 } from '../../mol-math/linear-algebra';
 import { RuntimeContext } from '../../mol-task';
 import { StringBuilder } from '../../mol-util';
@@ -35,6 +36,7 @@ export class ObjExporter extends MeshExporter<ObjData> {
     private currentColor: Color | undefined;
     private currentAlpha: number | undefined;
     private materialSet = new Set<string>();
+    private centerTransform: Mat4;
 
     private updateMaterial(color: Color, alpha: number) {
         if (this.currentColor === color && this.currentAlpha === alpha) return;
@@ -163,6 +165,7 @@ export class ObjExporter extends MeshExporter<ObjData> {
             const { vertices, normals, indices, groups, vertexCount, drawCount } = ObjExporter.getInstance(input, instanceIndex);
 
             Mat4.fromArray(t, aTransform, instanceIndex * 16);
+            Mat4.mul(t, this.centerTransform, t);
             mat3directionTransform(n, t);
 
             // position
@@ -273,8 +276,12 @@ export class ObjExporter extends MeshExporter<ObjData> {
         return new Blob([await zip(ctx, zipDataObj)], { type: 'application/zip' });
     }
 
-    constructor(private filename: string) {
+    constructor(private filename: string, boundingBox: Box3D) {
         super();
         StringBuilder.writeSafe(this.obj, `mtllib ${filename}.mtl\n`);
+        const tmpV = Vec3();
+        Vec3.add(tmpV, boundingBox.min, boundingBox.max);
+        Vec3.scale(tmpV, tmpV, -0.5);
+        this.centerTransform = Mat4.fromTranslation(Mat4(), tmpV);
     }
 }

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

@@ -5,6 +5,7 @@
  */
 
 import { asciiWrite } from '../../mol-io/common/ascii';
+import { Box3D } from '../../mol-math/geometry';
 import { Vec3, Mat4 } from '../../mol-math/linear-algebra';
 import { PLUGIN_VERSION } from '../../mol-plugin/version';
 import { RuntimeContext } from '../../mol-task';
@@ -26,6 +27,7 @@ export class StlExporter extends MeshExporter<StlData> {
     readonly fileExtension = 'stl';
     private triangleBuffers: ArrayBuffer[] = [];
     private triangleCount = 0;
+    private centerTransform: Mat4;
 
     protected async addMeshWithColors(input: AddMeshInput) {
         const { values, isGeoTexture, ctx } = input;
@@ -46,6 +48,7 @@ export class StlExporter extends MeshExporter<StlData> {
             const { vertices, indices, vertexCount, drawCount } = StlExporter.getInstance(input, instanceIndex);
 
             Mat4.fromArray(t, aTransform, instanceIndex * 16);
+            Mat4.mul(t, this.centerTransform, t);
 
             // position
             const vertexArray = new Float32Array(vertexCount * 3);
@@ -105,4 +108,12 @@ export class StlExporter extends MeshExporter<StlData> {
     async getBlob(ctx: RuntimeContext) {
         return new Blob([this.getData().stl], { type: 'model/stl' });
     }
+
+    constructor(boundingBox: Box3D) {
+        super();
+        const tmpV = Vec3();
+        Vec3.add(tmpV, boundingBox.min, boundingBox.max);
+        Vec3.scale(tmpV, tmpV, -0.5);
+        this.centerTransform = Mat4.fromTranslation(Mat4(), tmpV);
+    }
 }

+ 2 - 0
src/mol-canvas3d/canvas3d.ts

@@ -242,6 +242,7 @@ interface Canvas3D {
     requestCameraReset(options?: { durationMs?: number, snapshot?: Camera.SnapshotProvider }): void
     readonly camera: Camera
     readonly boundingSphere: Readonly<Sphere3D>
+    readonly boundingSphereVisible: Readonly<Sphere3D>
     setProps(props: PartialCanvas3DProps | ((old: Canvas3DProps) => Partial<Canvas3DProps> | void), doNotRequestDraw?: boolean /* = false */): void
     getImagePass(props: Partial<ImageProps>): ImagePass
     getRenderObjects(): GraphicsRenderObject[]
@@ -717,6 +718,7 @@ namespace Canvas3D {
             },
             camera,
             boundingSphere: scene.boundingSphere,
+            boundingSphereVisible: scene.boundingSphereVisible,
             get notifyDidDraw() { return notifyDidDraw; },
             set notifyDidDraw(v: boolean) { notifyDidDraw = v; },
             didDraw,