首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在Forge中创建多模型加载器和查看器

如何在Forge中创建多模型加载器和查看器
EN

Stack Overflow用户
提问于 2021-10-05 09:06:22
回答 1查看 222关注 0票数 0

我正在尝试构建一个Forge多模型查看器,该查看器可以从存储桶中获取/加载多个模型,并使用Nodejs在查看器中显示它们。

我使用了加载视图的教程,并正在寻找一种解决方法,将存储桶中的所有模型加载到Forge Viewer中。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-10-05 10:32:57

如果我理解正确的话,您想在视图顶部的模型教程中添加多个模型支持,对吗?

为此,我们需要调整ForgeViewer.js、ForgeTree.js和index.html

代码语言:javascript
运行
复制
//  ForgeViewer.js 
/////////////////////////////////////////////////////////////////////
// Copyright (c) Autodesk, Inc. All rights reserved
// Written by Forge Partner Development
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted,
// provided that the above copyright notice appears in all copies and
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE.  AUTODESK, INC.
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
/////////////////////////////////////////////////////////////////////

var viewer = null;

function launchViewer(models) {
  if (viewer != null) {
    viewer.tearDown()
    viewer.finish()
    viewer = null
    $("#forgeViewer").empty();
  }

  if (!models || models.length <= 0)
    return alert('Empty `models` input');

  var options = {
    env: 'MD20ProdUS',
    api: 'D3S',
    getAccessToken: getForgeToken
  };

  if (LMV_VIEWER_VERSION >= '7.48') {
    options.env = 'AutodeskProduction2';
    options.api = 'streamingV2';
  }

  Autodesk.Viewing.Initializer(options, () => {
    viewer = new Autodesk.Viewing.GuiViewer3D(document.getElementById('forgeViewer'));

    //load model one by one in sequence
    const util = new MultipleModelUtil(viewer);
    viewer.multipleModelUtil = util;

    // Use ShareCoordinates alignment instead
    // See https://github.com/yiskang/MultipleModelUtil for details
    // util.options = {
    //   alignment: MultipleModelAlignmentType.ShareCoordinates
    // };

    util.processModels(models);
  });
}

function getForgeToken(callback) {
  jQuery.ajax({
    url: '/api/forge/oauth/token',
    success: function (res) {
      callback(res.access_token, res.expires_in)
    }
  });
}
代码语言:javascript
运行
复制
// ForgeTree.js
/////////////////////////////////////////////////////////////////////
// Copyright (c) Autodesk, Inc. All rights reserved
// Written by Forge Partner Development
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted,
// provided that the above copyright notice appears in all copies and
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE.  AUTODESK, INC.
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
/////////////////////////////////////////////////////////////////////

$(document).ready(function () {
  prepareAppBucketTree();
  $('#refreshBuckets').click(function () {
    $('#appBuckets').jstree(true).refresh();
  });

  $('#createNewBucket').click(function () {
    createNewBucket();
  });

  $('#submitTranslation').click(function () {
    var treeNode = $('#appBuckets').jstree(true).get_selected(true)[0];
    submitTranslation(treeNode);
  });

  $('#createBucketModal').on('shown.bs.modal', function () {
    $("#newBucketKey").focus();
  });

  $('#CompositeTranslationModal').on('shown.bs.modal', function () {
    $("#rootDesignFilename").focus();
  });

  $('#hiddenUploadField').change(function () {
    var node = $('#appBuckets').jstree(true).get_selected(true)[0];
    var _this = this;
    if (_this.files.length == 0) return;
    var file = _this.files[0];
    switch (node.type) {
      case 'bucket':
        var formData = new FormData();
        formData.append('fileToUpload', file);
        formData.append('bucketKey', node.id);

        $.ajax({
          url: '/api/forge/oss/objects',
          data: formData,
          processData: false,
          contentType: false,
          type: 'POST',
          success: function (data) {
            $('#appBuckets').jstree(true).refresh_node(node);
            _this.value = '';
          }
        });
        break;
    }
  });

  $('#viewModels').click(function () {
    let treeInst = $('#appBuckets').jstree(true);
    let selectedNodeIds = $('#appBuckets').jstree('get_selected');
    let models = [];
    for (let i = 0; i < selectedNodeIds.length; i++) {
      let urn = selectedNodeIds[i];
      let node = treeInst.get_node(`${urn}_anchor`);
      if (!node || (node.type !== 'object'))
        continue;

      models.push({
        name: node.original.text,
        urn: `urn:${urn}`
      });
    }

    if (models.length <= 0 || (models.length !== selectedNodeIds.length))
      alert('Nothing selected or not all selected nodes are object-typed');

    launchViewer(models);
  });
});

function createNewBucket() {
  var bucketKey = $('#newBucketKey').val();
  var policyKey = $('#newBucketPolicyKey').val();
  jQuery.post({
    url: '/api/forge/oss/buckets',
    contentType: 'application/json',
    data: JSON.stringify({ 'bucketKey': bucketKey, 'policyKey': policyKey }),
    success: function (res) {
      $('#appBuckets').jstree(true).refresh();
      $('#createBucketModal').modal('toggle');
    },
    error: function (err) {
      if (err.status == 409)
        alert('Bucket already exists - 409: Duplicated')
      console.log(err);
    }
  });
}

function prepareAppBucketTree() {
  $('#appBuckets').jstree({
    'core': {
      'themes': { "icons": true },
      'data': {
        "url": '/api/forge/oss/buckets',
        "dataType": "json",
        'multiple': true,
        "data": function (node) {
          return { "id": node.id };
        }
      }
    },
    'types': {
      'default': {
        'icon': 'glyphicon glyphicon-question-sign'
      },
      '#': {
        'icon': 'glyphicon glyphicon-cloud'
      },
      'bucket': {
        'icon': 'glyphicon glyphicon-folder-open'
      },
      'object': {
        'icon': 'glyphicon glyphicon-file'
      }
    },
    "checkbox": {
      keep_selected_style: false,
      three_state: false,
      deselect_all: true,
      cascade: 'none'
    },
    "plugins": ["types", "checkbox", "state", "sort", "contextmenu"],
    contextmenu: { items: autodeskCustomMenu }
  }).on('loaded.jstree', function () {
    $('#appBuckets').jstree('open_all');
    $('#viewModels').show();
  // }).bind("activate_node.jstree", function (evt, data) {
  //   if (data != null && data.node != null && data.node.type == 'object') {
  //     $("#forgeViewer").empty();
  //     var urn = data.node.id;
  //     jQuery.ajax({
  //       url: '/api/forge/modelderivative/manifest/' + urn,
  //       success: function (res) {
  //         if (res.progress === 'success' || res.progress === 'complete') launchViewer(urn);
  //         else $("#forgeViewer").html('The translation job still running: ' + res.progress + '. Please try again in a moment.');
  //       },
  //       error: function (err) {
  //         var msgButton = 'This file is not translated yet! ' +
  //           '<button class="btn btn-xs btn-info" onclick="translateObject()"><span class="glyphicon glyphicon-eye-open"></span> ' +
  //           'Start translation</button>'
  //         $("#forgeViewer").html(msgButton);
  //       }
  //     });
  //   }
  });
}

function autodeskCustomMenu(autodeskNode) {
  var items;

  switch (autodeskNode.type) {
    case "bucket":
      items = {
        uploadFile: {
          label: "Upload file",
          action: function () {
            uploadFile();
          },
          icon: 'glyphicon glyphicon-cloud-upload'
        }
      };
      break;
    case "object":
      items = {
        translateFile: {
          label: "Translate",
          action: function () {
            var treeNode = $('#appBuckets').jstree(true).get_selected(true)[0];
            translateObject(treeNode);
          },
          icon: 'glyphicon glyphicon-eye-open'
        }
      };
      break;
  }

  return items;
}

function uploadFile() {
  $('#hiddenUploadField').click();
}

function submitTranslation(node) {
  $("#forgeViewer").empty();
  if (node == null) node = $('#appBuckets').jstree(true).get_selected(true)[0];
  var bucketKey = node.parents[0];
  var objectKey = node.id;
  var rootDesignFilename = $('#rootDesignFilename').val();
  var isSvf2 = $('#outputFormat :selected').text() === 'SVF2';
  var xAdsForce = ($('#xAdsForce').is(':checked') === true);
  var data = { 'bucketKey': bucketKey, 'objectName': objectKey, 'isSvf2': (isSvf2 === true), 'xAdsForce': xAdsForce };

  if((rootDesignFilename && rootDesignFilename.trim() && rootDesignFilename.trim().length > 0)) {
    data.rootFilename = rootDesignFilename;
    data.compressedUrn = true;
  }

  jQuery.post({
    url: '/api/forge/modelderivative/jobs',
    contentType: 'application/json',
    data: JSON.stringify(data),
    success: function (res) {
      $('#CompositeTranslationModal').modal('hide');
      $("#forgeViewer").html('Translation started! Please try again in a moment.');
    },
  });
}

function translateObject() {
  $('#CompositeTranslationModal').modal('show');
}
代码语言:javascript
运行
复制
<!DOCTYPE html>
<html>

<head>
  <title>Autodesk Forge Tutorial</title>
  <meta charset="utf-8" />
  <link rel="shortcut icon" href="https://github.com/Autodesk-Forge/learn.forge.viewmodels/raw/master/img/favicon.ico">
  <!-- Common packages: jQuery, Bootstrap, jsTree -->
  <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
  <script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
  <script src="//cdnjs.cloudflare.com/ajax/libs/jstree/3.3.7/jstree.min.js"></script>
  <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css">
  <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/jstree/3.3.7/themes/default/style.min.css" />
  <!-- Autodesk Forge Viewer files -->
  <link rel="stylesheet" href="https://developer.api.autodesk.com/modelderivative/v2/viewers/7.*/style.min.css" type="text/css">
  <script src="https://developer.api.autodesk.com/modelderivative/v2/viewers/7.*/viewer3D.js"></script>

  <script src="https://unpkg.com/@tweenjs/tween.js@18.6.4/dist/tween.umd.js"></script>
  <!-- MultipleModelUtil -->
  <script src="http://cdn.jsdelivr.net/gh/yiskang/MultipleModelUtil/MultipleModelUtil.js"></script>
  <!-- this project files -->
  <link href="css/main.css" rel="stylesheet" />
  <script src="js/ForgeTree.js"></script>
  <script src="js/ForgeViewer.js"></script>
</head>

<body>
  <!-- Fixed navbar by Bootstrap: https://getbootstrap.com/examples/navbar-fixed-top/ -->
  <nav class="navbar navbar-default navbar-fixed-top">
    <div class="container-fluid">
      <ul class="nav navbar-nav left">
        <li>
          <a href="http://developer.autodesk.com" target="_blank">
            <img alt="Autodesk Forge" src="//developer.static.autodesk.com/images/logo_forge-2-line.png" height="20">
          </a>
        </li>
      </ul>
    </div>
  </nav>
  <!-- End of navbar -->
  <div class="container-fluid fill">
    <div class="row fill">
      <div class="col-sm-2 fill">
        <div class="panel panel-default fill">
          <div class="panel-heading" data-toggle="tooltip">
            Buckets &amp; Objects
            <span id="refreshBuckets" class="glyphicon glyphicon-refresh" style="cursor: pointer"></span>
            <span id="viewModels" class="glyphicon glyphicon-eye-open" style="cursor: pointer; display: none" title="View selected models in the Forge Viewer"></span>
            <button class="btn btn-xs btn-info" style="float: right" id="showFormCreateBucket" data-toggle="modal" data-target="#createBucketModal">
              <span class="glyphicon glyphicon-folder-close"></span> New bucket
            </button>
          </div>
          <div id="appBuckets">
            tree here
          </div>
        </div>
      </div>
      <div class="col-sm-10 fill">
        <div id="forgeViewer"></div>
      </div>
    </div>
  </div>
  <form id="uploadFile" method='post' enctype="multipart/form-data">
    <input id="hiddenUploadField" type="file" name="theFile" style="visibility:hidden" />
  </form>
  <!-- Modal Create Bucket -->
  <div class="modal fade" id="createBucketModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
    <div class="modal-dialog" role="document">
      <div class="modal-content">
        <div class="modal-header">
          <button type="button" class="close" data-dismiss="modal" aria-label="Cancel">
            <span aria-hidden="true">&times;</span>
          </button>
          <h4 class="modal-title" id="myModalLabel">Create new bucket</h4>
        </div>
        <div class="modal-body">
          <input type="text" id="newBucketKey" class="form-control"> For demonstration purposes, objects (files)
          are NOT automatically translated. After you upload, right click on
          the object and select "Translate". Note: Technically your bucket name is required to be globally unique across
          the entire platform - to keep things simple with this tutorial your client ID will be prepended by default to
          your bucket name and in turn masked by the UI so you only have to make sure your bucket name is unique within
          your current Forge app.
        </div>
        <div class="modal-footer">
          <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
          <button type="button" class="btn btn-primary" id="createNewBucket">Go ahead, create the bucket</button>
        </div>
      </div>
    </div>
  </div>

  <!-- Composite model translation -->
  <div class="modal fade" id="CompositeTranslationModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
    <div class="modal-dialog" role="document">
      <div class="modal-content">
        <div class="modal-header">
          <button type="button" class="close" data-dismiss="modal" aria-label="Cancel">
            <span aria-hidden="true">&times;</span>
          </button>
          <h4 class="modal-title" id="myModalLabel">Composite Translation</h4>
        </div>
        <div class="modal-body">
          <div class="form-horizontal">
            <div class="form-group">
              <label for="outputFormat" class="col-sm-3 control-label">Output Format</label>
              <div class="col-sm-9">
                <select id="outputFormat" class="form-control">
                  <option>SVF</option>
                  <option selected="selected">SVF2</option>
                </select>
              </div>
            </div>
            <div class="form-group" style="margin-bottom: 0;">
              <label for="rootDesignFilename" class="col-sm-3 control-label">Root Filename</label>
              <div class="col-sm-9">
                <input type="text" id="rootDesignFilename" class="form-control" placeholder="Enter the filename of the root design">
              </div>
              <div class="col-sm-12">
                <span class="help-block" style="margin-bottom: 0; padding-left: 20px;">Enter the filename of the root design for the composite model. If the file is not a composite one, please press "Go ahead, submit translation" button directly.</span>
              </div>
            </div>
          </div>
        </div>
        <div class="modal-footer">
          <div class="checkbox pull-left">
            <label>
              <input type="checkbox" id="xAdsForce"> Replace previous result
            </label>
          </div>
          <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
          <button type="button" class="btn btn-primary" id="submitTranslation">Go ahead, submit translation</button>
        </div>
      </div>
    </div>
  </div>
</body>

</html>

下面是我所做的更改:https://github.com/yiskang/forge-viewmodels-nodejs-svf2/commit/5025b846970c2d95909b379f6704a51ca24caffd

下面是演示快照:

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69447683

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档