UNPKG

molstar

Version:

A comprehensive macromolecular library.

203 lines 12.3 kB
"use strict"; /** * Copyright (c) 2021 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Sukolsak Sakshuwong <sukolsak@stanford.edu> */ Object.defineProperty(exports, "__esModule", { value: true }); exports.ObjExporter = void 0; var tslib_1 = require("tslib"); var ascii_1 = require("../../mol-io/common/ascii"); var linear_algebra_1 = require("../../mol-math/linear-algebra"); var mol_util_1 = require("../../mol-util"); var color_1 = require("../../mol-util/color/color"); var zip_1 = require("../../mol-util/zip/zip"); var mesh_exporter_1 = require("./mesh-exporter"); // avoiding namespace lookup improved performance in Chrome (Aug 2020) var v3fromArray = linear_algebra_1.Vec3.fromArray; var v3transformMat4 = linear_algebra_1.Vec3.transformMat4; var v3transformMat3 = linear_algebra_1.Vec3.transformMat3; var mat3directionTransform = linear_algebra_1.Mat3.directionTransform; var ObjExporter = /** @class */ (function (_super) { (0, tslib_1.__extends)(ObjExporter, _super); function ObjExporter(filename, boundingBox) { var _this = _super.call(this) || this; _this.filename = filename; _this.fileExtension = 'zip'; _this.obj = mol_util_1.StringBuilder.create(); _this.mtl = mol_util_1.StringBuilder.create(); _this.vertexOffset = 0; _this.materialSet = new Set(); mol_util_1.StringBuilder.writeSafe(_this.obj, "mtllib " + filename + ".mtl\n"); var tmpV = (0, linear_algebra_1.Vec3)(); linear_algebra_1.Vec3.add(tmpV, boundingBox.min, boundingBox.max); linear_algebra_1.Vec3.scale(tmpV, tmpV, -0.5); _this.centerTransform = linear_algebra_1.Mat4.fromTranslation((0, linear_algebra_1.Mat4)(), tmpV); return _this; } ObjExporter.prototype.updateMaterial = function (color, alpha) { if (this.currentColor === color && this.currentAlpha === alpha) return; this.currentColor = color; this.currentAlpha = alpha; var material = color_1.Color.toHexString(color) + alpha; mol_util_1.StringBuilder.writeSafe(this.obj, "usemtl " + material); mol_util_1.StringBuilder.newline(this.obj); if (!this.materialSet.has(material)) { this.materialSet.add(material); var _a = color_1.Color.toRgbNormalized(color), r = _a[0], g = _a[1], b = _a[2]; var mtl = this.mtl; mol_util_1.StringBuilder.writeSafe(mtl, "newmtl " + material + "\n"); mol_util_1.StringBuilder.writeSafe(mtl, 'illum 2\n'); // illumination model mol_util_1.StringBuilder.writeSafe(mtl, 'Ns 163\n'); // specular exponent mol_util_1.StringBuilder.writeSafe(mtl, 'Ni 0.001\n'); // optical density a.k.a. index of refraction mol_util_1.StringBuilder.writeSafe(mtl, 'Ka 0 0 0\n'); // ambient reflectivity mol_util_1.StringBuilder.writeSafe(mtl, 'Kd '); // diffuse reflectivity mol_util_1.StringBuilder.writeFloat(mtl, r, 1000); mol_util_1.StringBuilder.whitespace1(mtl); mol_util_1.StringBuilder.writeFloat(mtl, g, 1000); mol_util_1.StringBuilder.whitespace1(mtl); mol_util_1.StringBuilder.writeFloat(mtl, b, 1000); mol_util_1.StringBuilder.newline(mtl); mol_util_1.StringBuilder.writeSafe(mtl, 'Ks 0.25 0.25 0.25\n'); // specular reflectivity mol_util_1.StringBuilder.writeSafe(mtl, 'd '); // dissolve mol_util_1.StringBuilder.writeFloat(mtl, alpha, 1000); mol_util_1.StringBuilder.newline(mtl); } }; ObjExporter.prototype.addMeshWithColors = function (input) { return (0, tslib_1.__awaiter)(this, void 0, void 0, function () { var mesh, values, isGeoTexture, webgl, ctx, obj, t, n, tmpV, stride, groupCount, colorType, uAlpha, dTransparency, tTransparency, aTransform, instanceCount, interpolatedColors, instanceIndex, _a, vertices, normals, indices, groups, vertexCount, drawCount, i, i, i, v, color, alpha, group, transparency, v1, v2, v3; return (0, tslib_1.__generator)(this, function (_b) { switch (_b.label) { case 0: mesh = input.mesh, values = input.values, isGeoTexture = input.isGeoTexture, webgl = input.webgl, ctx = input.ctx; obj = this.obj; t = (0, linear_algebra_1.Mat4)(); n = (0, linear_algebra_1.Mat3)(); tmpV = (0, linear_algebra_1.Vec3)(); stride = isGeoTexture ? 4 : 3; groupCount = values.uGroupCount.ref.value; colorType = values.dColorType.ref.value; uAlpha = values.uAlpha.ref.value; dTransparency = values.dTransparency.ref.value; tTransparency = values.tTransparency.ref.value; aTransform = values.aTransform.ref.value; instanceCount = values.uInstanceCount.ref.value; if (colorType === 'volume' || colorType === 'volumeInstance') { interpolatedColors = ObjExporter.getInterpolatedColors(mesh.vertices, mesh.vertexCount, values, stride, colorType, webgl); ObjExporter.quantizeColors(interpolatedColors, mesh.vertexCount); } return [4 /*yield*/, ctx.update({ isIndeterminate: false, current: 0, max: instanceCount })]; case 1: _b.sent(); instanceIndex = 0; _b.label = 2; case 2: if (!(instanceIndex < instanceCount)) return [3 /*break*/, 6]; if (!ctx.shouldUpdate) return [3 /*break*/, 4]; return [4 /*yield*/, ctx.update({ current: instanceIndex + 1 })]; case 3: _b.sent(); _b.label = 4; case 4: _a = ObjExporter.getInstance(input, instanceIndex), vertices = _a.vertices, normals = _a.normals, indices = _a.indices, groups = _a.groups, vertexCount = _a.vertexCount, drawCount = _a.drawCount; linear_algebra_1.Mat4.fromArray(t, aTransform, instanceIndex * 16); linear_algebra_1.Mat4.mul(t, this.centerTransform, t); mat3directionTransform(n, t); // position for (i = 0; i < vertexCount; ++i) { v3transformMat4(tmpV, v3fromArray(tmpV, vertices, i * stride), t); mol_util_1.StringBuilder.writeSafe(obj, 'v '); mol_util_1.StringBuilder.writeFloat(obj, tmpV[0], 1000); mol_util_1.StringBuilder.whitespace1(obj); mol_util_1.StringBuilder.writeFloat(obj, tmpV[1], 1000); mol_util_1.StringBuilder.whitespace1(obj); mol_util_1.StringBuilder.writeFloat(obj, tmpV[2], 1000); mol_util_1.StringBuilder.newline(obj); } // normal for (i = 0; i < vertexCount; ++i) { v3transformMat3(tmpV, v3fromArray(tmpV, normals, i * stride), n); mol_util_1.StringBuilder.writeSafe(obj, 'vn '); mol_util_1.StringBuilder.writeFloat(obj, tmpV[0], 100); mol_util_1.StringBuilder.whitespace1(obj); mol_util_1.StringBuilder.writeFloat(obj, tmpV[1], 100); mol_util_1.StringBuilder.whitespace1(obj); mol_util_1.StringBuilder.writeFloat(obj, tmpV[2], 100); mol_util_1.StringBuilder.newline(obj); } // face for (i = 0; i < drawCount; i += 3) { v = isGeoTexture ? i : indices[i]; color = ObjExporter.getColor(values, groups, vertexCount, instanceIndex, isGeoTexture, interpolatedColors, v); alpha = uAlpha; if (dTransparency) { group = isGeoTexture ? ObjExporter.getGroup(groups, i) : groups[indices[i]]; transparency = tTransparency.array[instanceIndex * groupCount + group] / 255; alpha *= 1 - transparency; } this.updateMaterial(color, alpha); v1 = this.vertexOffset + (isGeoTexture ? i : indices[i]) + 1; v2 = this.vertexOffset + (isGeoTexture ? i + 1 : indices[i + 1]) + 1; v3 = this.vertexOffset + (isGeoTexture ? i + 2 : indices[i + 2]) + 1; mol_util_1.StringBuilder.writeSafe(obj, 'f '); mol_util_1.StringBuilder.writeInteger(obj, v1); mol_util_1.StringBuilder.writeSafe(obj, '//'); mol_util_1.StringBuilder.writeIntegerAndSpace(obj, v1); mol_util_1.StringBuilder.writeInteger(obj, v2); mol_util_1.StringBuilder.writeSafe(obj, '//'); mol_util_1.StringBuilder.writeIntegerAndSpace(obj, v2); mol_util_1.StringBuilder.writeInteger(obj, v3); mol_util_1.StringBuilder.writeSafe(obj, '//'); mol_util_1.StringBuilder.writeInteger(obj, v3); mol_util_1.StringBuilder.newline(obj); } this.vertexOffset += vertexCount; _b.label = 5; case 5: ++instanceIndex; return [3 /*break*/, 2]; case 6: return [2 /*return*/]; } }); }); }; ObjExporter.prototype.getData = function () { return (0, tslib_1.__awaiter)(this, void 0, void 0, function () { return (0, tslib_1.__generator)(this, function (_a) { return [2 /*return*/, { obj: mol_util_1.StringBuilder.getString(this.obj), mtl: mol_util_1.StringBuilder.getString(this.mtl) }]; }); }); }; ObjExporter.prototype.getBlob = function (ctx) { return (0, tslib_1.__awaiter)(this, void 0, void 0, function () { var _a, obj, mtl, objData, mtlData, zipDataObj, _b; var _c; return (0, tslib_1.__generator)(this, function (_d) { switch (_d.label) { case 0: return [4 /*yield*/, this.getData()]; case 1: _a = _d.sent(), obj = _a.obj, mtl = _a.mtl; objData = new Uint8Array(obj.length); (0, ascii_1.asciiWrite)(objData, obj); mtlData = new Uint8Array(mtl.length); (0, ascii_1.asciiWrite)(mtlData, mtl); zipDataObj = (_c = {}, _c[this.filename + '.obj'] = objData, _c[this.filename + '.mtl'] = mtlData, _c); _b = Blob.bind; return [4 /*yield*/, (0, zip_1.zip)(ctx, zipDataObj)]; case 2: return [2 /*return*/, new (_b.apply(Blob, [void 0, [_d.sent()], { type: 'application/zip' }]))()]; } }); }); }; return ObjExporter; }(mesh_exporter_1.MeshExporter)); exports.ObjExporter = ObjExporter; //# sourceMappingURL=obj-exporter.js.map