NSDT工具推荐: Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 可编程3D场景编辑器 - REVIT导出3D模型插件 - 3D模型语义搜索引擎 - AI模型在线查看 - Three.js虚拟轴心开发包 - 3D模型在线减面 - STL模型在线切割 - 3D道路快速建模
Sketchfab 的 API 使你能够以编程方式访问网络上最大的 glTF 3D 模型集合。 本文通过一个最小的代码示例向你展示如何:
- 让你的用户使用 Sketchfab API 进行身份验证
- 将 3D 模型下载为包含 glTF 的 zip 文件
- 将此 zip 文件加载到 ThreeJS
源代码可以从这里下载。
1、使用方法
我最初实现这个是为了让我的 WebGL 大纲教程的读者看到效果在他们选择的测试用例上的样子。 因为我一直在寻找对我的特定极端情况不起作用的算法(但直到我实现它/下载并运行它之后我才发现!)
这是一种让用户引入自己的数据(或数百万个示例模型)的非常简单的方法。
可以在这个 outlines 现场演示中看到它是如何工作的:
- 打开演示
- 单击登录到 Sketchfab
- 当返回到应用程序时,将模型链接粘贴到 Sketchfab URL 字段中,例如:
https://sketchfab.com/3d-models/skull-downloadable-1a9db900738d44298b0bc59f68123393
该模型必须可由已登录的 Sketchfab 帐户下载。
2、使用 Sketchfab API 进行身份验证
第一步是向 Sketchfab 注册你的应用程序。 这方面的说明在这里。
你需要选择一个重定向 URI。 这应该是你将在其中部署应用程序的最终 URI。
你需要使用隐式授权类型。 我们不能在 Web 应用程序中将 API 密钥保密,因此我们改为依赖重定向 URI(如果有人恶意使用你的客户端 ID,Sketchfab 将在登录后将他们重定向到你的真实应用程序,无论是谁发起的 登录)。
注册应用程序后,你将拥有一个客户端 ID。你将使用它来将用户发送到 Sketchfab 进行登录,如下所示:
const CLIENT_ID = 'YOUR_CLIENT_ID_HERE';
const AUTHENTICATION_URL = `https://sketchfab.com/oauth2/authorize/?state=123456789&response_type=token&client_id=${CLIENT_ID}`;
window.open(AUTHENTICATION_URL, '_blank');
登录完成后,你需要从 URL 中获取访问令牌。 这是执行此操作并将其存储在本地存储中的代码段:
checkToken() {
// Check if there's a new token from the URL
const url = new URL(window.location)
// Extract the token and save it
const hashParams = url.hash.split('&');
for (let param of hashParams) {
if (param.indexOf("access_token") !== -1) {
const token = param.replace('#access_token=', '');
console.log("Detected Sketchfab token: ", token);
localStorage.setItem("sb_token", token);
}
}
// Load token from local storage
this.token = localStorage.getItem("sb_token");
}
你将在后续 API 调用中使用此令牌。
注意:当你在本地开发时,Sketchfab 将重定向到生产 URI。 你需要将 URI 参数复制到本地主机以进行测试。
2 、下载 3D 模型
获得令牌后,你可以使用它来获取 glTF 模型的下载 URI。
这是在给定任何 Sketchfab URI 的情况下获取下载 URI 的代码片段:
async getModelDownloadUrl(inputUrl) {
// Extract the model ID from the URL
const input = new URL(inputUrl);
// The ID is always the last string when seperating by '-'
const pieces = input.pathname.split('-');
const modelID = pieces[pieces.length - 1];
const metadataUrl = `https://api.sketchfab.com/v3/models/${modelID}/download`;
const options = {
method: 'GET',
headers: {
Authorization: `Bearer ${this.token}`,
},
mode: 'cors'
};
// This call will fail if model can't be downloaded
const response = await fetch(metadataUrl, options);
const metadata = await response.json();
return metadata.gltf.url;
}
请注意,如果登录的用户无权下载此模型,则此请求将失败。 这适用于需要购买的商店模型或不可下载的免费模型。
你可以在 Sketchfab 搜索中过滤可下载模型:
这将向你显示可以下载的免费模型或可以购买的模型。
现在我们有了一个包含 glTF 模型的 zip 文件的 URL,我们可以将它传递给 ThreeJS 来加载它。
3、将 ZIP 文件加载到 ThreeJS
这是我最棘手的部分。 通常 ThreeJS 需要 glTF 文件的直接 URL。 要从 zip 文件加载它,我们将需要:
- 使用 JSZip 将内容解压缩到内存中。我们不能只将解压缩的原始内容传递给 ThreeJS,因为 glTF 文件可能通过文件路径(图像或几何资源)引用其他文件。
- 为每个资源创建一个 Blob,并且
- 覆盖 glTF 文件使用 Blob URI 请求的资源。
例如,如果 glTF 文件试图将 textures/defaultMat_baseColor.jpeg 作为相对文件路径加载,我们会检测到这一点,并传递此 URI:
//Unzip from JSZip
const file = unzippedBaseColorJPEGFile;
// Create a Blob from this file
const blob = await file.async('blob');
// Create a URL to this Blob
const baseColorBlobUrl = URL.createObjectURL(blob);
// Use ThreeJS's loading manager so instead of loading from relative filepaths we load from the blob URI's we created
const loadingManager = new THREE.LoadingManager(); loadingManager.setURLModifier((url) => {
if (url == 'textures/defaultMat_baseColor.jpeg') {
return baseColorBlobUrl;
}
});
我们使用 ThreeJS 的 LoadingManager
来做到这一点。
下面是代码片段,它可以获取任何压缩 glTF 的 URL 并将其加载到 ThreeJS 中:
async readZip(zipUrl, scene) {
const response = await fetch(zipUrl);
checkStatus(response);
const arrayBuffer = await response.arrayBuffer();
const result = await JSZip.loadAsync(arrayBuffer);
const files = Object.values(result.files).filter(item => !item.dir);
const entryFile = files.find(f => getExtension(f.name) === 'gltf');
// Create blobs for every file resource
const blobUrls = {};
for (const file of files) {
console.log(`Loading ${file.name}...`);
blobUrls[file.name] = await getFileUrl(file);
}
const fileUrl = blobUrls[entryFile.name];
scene.clear();
// Re-add the light
const light = new THREE.DirectionalLight(0xffffff, 1);
scene.add(light);
light.position.set(1.7, 1, -1);
const loadingManager = new THREE.LoadingManager();
loadingManager.setURLModifier((url) => {
const parsedUrl = new URL(url);
const origin = parsedUrl.origin;
const path = parsedUrl.pathname;
const relativeUrl = path.replace(origin + '/', "");
if (blobUrls[relativeUrl] != undefined) {
return blobUrls[relativeUrl];
}
return url
});
const gltfLoader = new GLTFLoader(loadingManager);
gltfLoader.load(fileUrl, (gltf) => {
scene.add(gltf.scene);
});
}
4、显示属性
在你的应用程序中使用来自 Sketchfab 的 3D 模型需要你显示原作者的署名。 关于这一点,可以在 Sketchfab 上阅读更多相关信息。
我们可以从这个数据 API 路由中自动获取属性和许可信息。
这是一个函数,它将在给定 modelID 的情况下构造属性文本:
async getAttributionText(modelID) {
const modelDataUrl = `https://api.sketchfab.com/v3/models/${modelID}`;
const options = {
method: 'GET',
headers: {
Authorization: `Bearer ${this.token}`,
},
mode: 'cors'
};
const response = await fetch(modelDataUrl, options);
const metadata = await response.json();
const license = { name: metadata.license.label, url: metadata.license.url };
const user = { name: metadata.user.displayName , url: metadata.user.profileUrl };
const model = { name: metadata.name, url: metadata.viewerUrl };
const attributionText =
`This work is based on <a href="${model.url}" target=_blank>${model.name}</a>
by <a href="${user.url}" target=_blank>${user.name}</a>
licensed under <a href="${license.url}" target=_blank>${license.name}</a>.`;
return attributionText;
}
示例应用程序将在左下角显示属性,链接到原始模型 URL、作者的 Sketchfab 个人资料和许可证。
5、已知的问题
加载某些 Sketchfab 模型的一个问题是它们的比例将比当前视口大得多。 另一个问题是某些模型可能不以原点为中心,因此加载时它们可能不可见。
在 ThreeJS 中加载模型时规范化和缩放模型将有助于解决这个问题,类似于这个 glTF在线查看工具的工作方式。
原文链接:How to load Sketchfab models directly in a ThreeJS app
BimAnt翻译整理,转载请标明出处