KEMBAR78
Sketchfab Script | PDF | Imaging | Computer Vision
0% found this document useful (0 votes)
58 views6 pages

Sketchfab Script

The document is a user script for Sketchfab that allows users to download textures from 3D models. It includes functions to manipulate WebGL rendering context, create download buttons, and handle texture data extraction. The script is designed to work on specific Sketchfab model pages and requires certain conditions to function properly.

Uploaded by

akunkorban57
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
58 views6 pages

Sketchfab Script

The document is a user script for Sketchfab that allows users to download textures from 3D models. It includes functions to manipulate WebGL rendering context, create download buttons, and handle texture data extraction. The script is designed to work on specific Sketchfab model pages and requires certain conditions to function properly.

Uploaded by

akunkorban57
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 6

// ==UserScript==

// @name SketchfabTextureDump_V3
// @namespace Violentmonkey Scripts
// @match *://*.sketchfab.com/3d-models/**
// @match *://*.sketchfab.com/models/**
// @grant none
// @version 0.0.3
// @author krapnik
// @create-time 2023/7/31 22:59:46
// @license MIT
// @run-at document-start
// ==/UserScript==
(function () {

const MIN_TEXTURE_WIDTH = 256,


MIN_TEXTURE_HEIGHT = 256;
let _log = console.log;
let _warn = console.warn;
let model_name = location.pathname.split("/")[2];
let model_name_arr = model_name.split("-");
let model_id = model_name_arr[model_name_arr.length - 1];
let downloadCnt = 0;
let originTextureArr = [];
if (location.href.indexOf('sketchfab.com/3d-models/') > -1) {
return;
}
if (window.self !== window.top) {
setTimeout(() => {
addViewBtn();
}, 3000)
return;
}
_log("=======SketchfabTextureDump=======");
if (!model_id) {
_warn("can't find model_id!");
return;
} else {
_log("model_id:", model_id);
}

window.onload = () => {
try {
let results = window.prefetchedData[`/i/models/${model_id}/textures?
optimized=1`].results;
coverTexture(results); // quality high
Object.defineProperty(window.prefetchedData[`/i/models/${model_id}/textures?
optimized=1`], "results", {
get: () => {
return results;
}
})
originTextureArr = window.prefetchedData[`/i/models/${model_id}/textures?
optimized=1`].results || [];
} catch (e) {
_warn('oops~something went wrong,u can refresh the page & try again');
}
}

function coverTexture(results) {
results.forEach((texture) => {
let images = texture.images;
let img = images[images.length - 2];
texture.url = img.url;
images.forEach((item, idx) => {
images[idx] = img;
})
})
}

function addDownloadBtn() {
let btn = document.createElement("button");
btn.innerHTML = "download";
btn.style.position = "absolute"
btn.style.top = "0"
btn.style.left = "0"
document.body.appendChild(btn);
btn.onclick = dumpWebGLTextureData;
}

function addViewBtn() {
let btn = document.createElement("button");
btn.innerHTML = "goto download";
btn.style.position = "absolute"
btn.style.top = "0"
btn.style.left = "0"
document.body.appendChild(btn);
btn.onclick = () => {
let link = document.createElement("a");
link.setAttribute("href", `https://sketchfab.com/models/${model_id}/embed?
autostart=1&internal=1&tracking=0&ui_ar=0&ui_infos=0&ui_snapshots=1&ui_stop=0&ui_th
eatre=1&ui_watermark=0`);
link.setAttribute("target", "_blank");
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
};
}

let webGLTextureIdx = 0;
let webGLTextureMap = {};
document.addEventListener("DOMContentLoaded", function () {
var str = document.querySelector("#js-dom-data-prefetched-
data").innerHTML.replace("\x3C!--", "").replace("-->", "").replaceAll(""",
"\"");
var prefetchedData = JSON.parse(str);
let context = prefetchedData.embedOptions.webgl2 ? WebGL2RenderingContext :
WebGLRenderingContext;
hookWebGLRenderingContext(context);
}, false);

function hookWebGLRenderingContext(context) {
//createTexture
let glCreateTexture = context.prototype.createTexture;
context.prototype.createTexture = function (...args) {
let texture = glCreateTexture.apply(this, args);
texture.name = webGLTextureIdx;
texture.gl = this;
webGLTextureMap[`${webGLTextureIdx}`] = texture;
webGLTextureIdx++;
return texture;
};

//bindTexture
let glBindTexture = context.prototype.bindTexture;
context.prototype.bindTexture = function (...args) {
let target = args[0], texture = args[1];
if (texture) {
texture.target = target;
}
glBindTexture.apply(this, args);
};

let glDeleteTexture = context.prototype.deleteTexture;


context.prototype.deleteTexture = function (...args) {
// do notthing
};

//texImage
let lstTexture;
let glTexImage2D = context.prototype.texImage2D;
let hasCoverTex = 0;
let isAllTextureCover = false;
context.prototype.texImage2D = function (...args) {
let texture = this.getParameter(this.TEXTURE_BINDING_2D) ||
this.getParameter(this.TEXTURE_BINDING_CUBE_MAP);
let argments = parseTexImage2dArgs(args);
if (texture.target == argments.target) {
texture.args = argments;
let { width, height, src } = argments;
if (
width > MIN_TEXTURE_WIDTH &&
height > MIN_TEXTURE_HEIGHT &&
(width & width - 1) === 0 &&
(height & height - 1) === 0 &&
texture.target === this.TEXTURE_2D
) {
if (src) {
// let textureName = getFileNameByLink(src);
texture.src = argments.src;
lstTexture.lst = texture.name;
hasCoverTex++;
_log(`【origin texture cover】 total:${originTextureArr.length} count:$
{hasCoverTex}`);
if (originTextureArr.length == hasCoverTex) {
isAllTextureCover = true;
_log('all files are ready! click the 【download】 button');
addDownloadBtn();
}
}
lstTexture = texture;
}
}
glTexImage2D.apply(this, args);
};
}

function parseTexImage2dArgs(args) {
let argments = {};
if (args.length == 6) {
let [target, level, internalformat, format, type, source] = args;
let { width, height, src } = source;
argments = { target, level, width, height, internalformat, format, type,
src };
} else if (args.length == 9) {
let [
target,
level,
internalformat,
width,
height,
border,
format,
type,
pixels,
] = args;
argments = { target, level, width, height, format, internalformat, type };
} else {
let [target] = args;
argments = { target };
}
return argments;
}

function readWebTextureData(texture) {
let { target, gl, args, src, lst } = texture;
if (!args) { // todo maybe other func bind
return
}
let { level, width, height, format, internalformat, type } = args;
if (
width > MIN_TEXTURE_WIDTH &&
height > MIN_TEXTURE_HEIGHT &&
(width & width - 1) === 0 &&
(height & height - 1) === 0 &&
target === gl.TEXTURE_2D &&
!src
) {
let fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
gl.framebufferTexture2D(
gl.FRAMEBUFFER,
gl.COLOR_ATTACHMENT0,
gl.TEXTURE_2D,
texture,
level
);
let framebufferStatus = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
if (
framebufferStatus == gl.FRAMEBUFFER_COMPLETE
) {
let fileName = `${Date.now()}.png`;
let originName = fileName;
let originTex = webGLTextureMap[lst];
if (originTex) {
if (originTex && originTex.src) {
let path = originTex.src.split("/");
let uid = path[path.length - 2];
originName = getNameById(uid);
}
if (fileName == originName || !originName) { return }
let pixels = new Uint8Array(width * height * 4);
gl.readPixels(0, 0, width, height, format, type, pixels);
let canvas = document.createElement("canvas");
canvas.width = width;
canvas.height = height;
let context = canvas.getContext("2d");
let imageData = context.createImageData(width, height);
imageData.data.set(pixels);
context.putImageData(imageData, 0, 0);
downloadCnt++;
downLoadByLink(canvas.toDataURL(), originName); // todo format
}
}
}
}

function dumpWebGLTextureData() {
downloadCnt = 0;
for (let key in webGLTextureMap) {
readWebTextureData(webGLTextureMap[key]);
}
if (downloadCnt == originTextureArr.length) {
_log(`【dump texture:${downloadCnt}/${originTextureArr.length}】 success!`);
} else {
_log(`【dump texture:${downloadCnt}/${originTextureArr.length}】oops~something
went wrong,u can refresh the page & try again`);
}
}

function getNameById(uid) {
let name;
let texture = originTextureArr.find((t) => {
return t.uid == uid;
});
if (texture) {
name = texture.name;
}
return name;
}

function downLoadByLink(url, filename) {


let link, evt;
link = document.createElement('a');
link.href = url;
filename && link.setAttribute('download', filename);
if (document.fireEvent) {
window.open(link.href);
} else {
evt = document.createEvent('MouseEvents');
evt.initEvent('click', true, true);
link.dispatchEvent(evt);
}
};
window.dumpWebGLTextureData = dumpWebGLTextureData;
})();

You might also like