Ок, спасибо, Спулае ! Нужно будет покопаться в этой проблематике. Сугубо ради интереса.Ну да, это именно одна из таких моделей. Нужно найти просто её аналог
Посмотреть вложение 265174
Ок, спасибо, Спулае ! Нужно будет покопаться в этой проблематике. Сугубо ради интереса.Ну да, это именно одна из таких моделей. Нужно найти просто её аналог
Посмотреть вложение 265174
// ==UserScript==
// @name SketchfabDownloader_V3
// @version 3
// @description Download sketchfab models & textures for FREE! (as it SHOULD be)
// @author shitposting goddess (legend)
// @support https://discord.gg/free-stuff-1052920619152449596
// @include /^https?://(www\.)?sketchfab\.com/.*
// @require https://cdnjs.cloudflare.com/ajax/libs/jszip/3.1.5/jszip.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/jszip-utils/0.0.2/jszip-utils.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/1.3.8/FileSaver.js
// @run-at document-start
// @grant unsafeWindow
// @grant GM_download
// ==/UserScript==
//debugger;
var zip = new JSZip(); // Ignore the warnings, they refer to markdown v3
let folder = zip.folder('collection');
var button_dw = false;
var func_drawGeometry = /(this\._stateCache\.drawGeometry\(this\._graphicContext,t\))/g;
var fund_drawArrays = /t\.drawArrays\(t\.TRIANGLES,0,6\)/g;
var func_renderInto1 = /x\.renderInto\(n,S,y/g;
var func_renderInto2 = /g\.renderInto=function\(e,i,r/g;
var func_getResourceImage = /getResourceImage:function\(e,t\){/g;
//unsuportted model
var func_RenderLeaf_computed_drawGeometry = /else (\w{1}\(this,t,a\))/g;
var func_test = /apply:function\(e\){var t=e instanceof r\.Geometry;/g
var addbtnfunc;
(function() {
'use strict';
var window = unsafeWindow;
console.log("[UserScript]init", window);
window.allmodel = [];
var saveimagecache2 = {};
var objects = {};
var saveimage_to_list = function(url,file_name)
{
if (!saveimagecache2[url])
{
var mdl = {
name: file_name
}
saveimagecache2[url] = mdl;
}
}
addbtnfunc = function() {
var p = document.evaluate("//div[@class='titlebar']", document, null, 9, null).singleNodeValue;
if(p && !button_dw) {
console.log("[UserScript]add btn dwnld");
var btn = document.createElement("a");
btn.setAttribute("class", "control");
btn.innerHTML = "<pre style='font-family:impact;font-size:36px;text-shadow: 1px 1px black;color:#4cbd48;'>CLICK TO DOWNLOAD</pre>";
btn.addEventListener('click', () => {
alert('Zipping files...') })
btn.addEventListener("click", dodownload , false);
p.appendChild(btn);
button_dw = true;
} else {
console.log("[UserScript]try add btn later");
setTimeout(addbtnfunc, 3000);
}
}
var dodownload = function() {
console.log("[UserScript]download");
var idx = 0;
window.allmodel.forEach(function(obj)
{
var mdl = {
name: obj._name ? obj._name + "_" +obj._instanceID : "model_"+ idx++,
obj: parseobj(obj)
}
console.log(mdl);
dosavefile(mdl);
//idx++;
})
PackAll();
}
var PackAll = function ()
{
for (var obj in objects) {
console.log("[UserScript]save file", obj);
folder.file(obj, objects[obj], {binary:true});
}
var file_name = document.getElementsByClassName('model-name__label')[0].textContent;
folder.generateAsync({ type: "blob" }).then(content => saveAs(content, file_name + ".zip")); // Ignore the warnings, they refer to markdown v3
}
var parseobj = function(obj)
{
console.log("[UserScript]: obj", obj);
var list = [];
obj._primitives.forEach(function(p) {
if(p && p.indices) {
list.push({
'mode' : p.mode,
'indices' : p.indices._elements
});
}
})
var attr = obj._attributes;
return {
vertex: attr.Vertex._elements,
normal: attr.Normal ? attr.Normal._elements : [],
uv: attr.TexCoord0 ? attr.TexCoord0._elements :
attr.TexCoord1 ? attr.TexCoord1._elements :
attr.TexCoord2 ? attr.TexCoord2._elements :
attr.TexCoord2 ? attr.TexCoord2._elements :
attr.TexCoord3 ? attr.TexCoord3._elements :
attr.TexCoord4 ? attr.TexCoord4._elements :
attr.TexCoord5 ? attr.TexCoord5._elements :
attr.TexCoord6 ? attr.TexCoord6._elements :
attr.TexCoord7 ? attr.TexCoord7._elements :
attr.TexCoord8 ? attr.TexCoord8._elements : [], // Ignore the warnings, they refer to markdown v3
primitives: list,
};
}
var dosavefile = function(mdl)
{
var obj = mdl.obj;
//console.log("TEST");
//console.log(obj);
var str = '';
str += 'mtllib ' + mdl.name + '.mtl\n';
str += 'o ' + mdl.name + '\n';
for (var i = 0; i < obj.vertex.length; i += 3) {
str += 'v ';
for (var j = 0; j < 3; ++j) {
str += obj.vertex[i + j] + ' ';
}
str += '\n';
}
for (i = 0; i < obj.normal.length; i += 3) {
str += 'vn ';
for (j = 0; j < 3; ++j) {
str += obj.normal[i + j] + ' ';
}
str += '\n';
}
for (i = 0; i < obj.uv.length; i += 2) {
str += 'vt ';
for (j = 0; j < 2; ++j) {
str += obj.uv[i + j] + ' ';
}
str += '\n';
}
//str += 'usemtl ' + mdl.name + '\n';
str += 's on \n';
var vn = obj.normal.length != 0;
var vt = obj.uv.length != 0;
for (i = 0; i < obj.primitives.length; ++i) {
var primitive = obj.primitives[i];
if (primitive.mode == 4 || primitive.mode == 5) {
var strip = (primitive.mode == 5);
for (j = 0; j + 2 < primitive.indices.length; !strip ? j += 3 : j++) {
str += 'f ';
var order = [ 0, 1, 2];
if (strip && (j % 2 == 1)) {
order = [ 0, 2, 1];
}
for (var k = 0; k < 3; ++k)
{
var faceNum = primitive.indices[j + order[k]] + 1;
str += faceNum;
if (vn || vt) {
str += '/';
if (vt) {
str += faceNum;
}
if (vn) {
str += '/' + faceNum;
}
}
str += ' ';
}
str += '\n';
}
}
else {
console.log("[UserScript]dosavefile: unknown primitive mode", primitive);
}
}
str += '\n';
var objblob = new Blob([str], {type:'text/plain'});
objects[mdl.name+".obj"] = objblob;
}
window.attachbody = function(obj)
{
if(obj._faked != true && ((obj.stateset && obj.stateset._name) || obj._name || (obj._parents && obj._parents[0]._name)) ) {
obj._faked = true;
if(obj._name == "composer layer" || obj._name == "Ground - Geometry") return;
window.allmodel.push(obj)
console.log(obj);
}
//console.log(obj);
}
window.hook_test = function(e, idx)
{
console.log("hooked index: "+idx);
console.log(e);
}
window.drawhookcanvas = function(e, imagemodel)
{
return;
if((e.width == 128 && e.height == 128) || (e.width == 32 && e.height == 32) || (e.width == 64 && e.height == 64))
{
return e;
}
if(imagemodel)
{
var alpha = e.options.format;
var filename_image = imagemodel.attributes.name; // Ignore the warnings, they refer to markdown v3
var uid = imagemodel.attributes.uid;
var url_image = e.url;
var max_size = 0;
var obr = e;
imagemodel.attributes.images.forEach(function(img)
{
var alpha_is_check = alpha == "A" ? img.options.format == alpha : true;
var d = img.width;
while ( d % 2 == 0 )
{
d = d / 2;
}
if(img.size > max_size && alpha_is_check && d == 1)
{
max_size = img.size;
url_image = img.url;
uid = img.uid;
obr = img;
}
});
if(!saveimagecache2[url_image])
{
console.log(e);
saveimage_to_list(url_image, filename_image);
}
else
{
//console.log(e);
}
return obr;
}
return e;
}
window.drawhookimg = function(gl,t)
{
return;
var url = t[5].currentSrc;
var width = t[5].width;
var height = t[5].height;
if(!saveimagecache2[url])
{
//console.log("rejected:"+url);
return;
}
else
{
//console.log("saved texture:"+url);
}
var data = new Uint8Array(width * height * 4);
gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, data);
var halfHeight = height / 2 | 0; // the | 0 keeps the result an int
var bytesPerRow = width * 4;
// make a temp buffer to hold one row
var temp = new Uint8Array(width * 4);
for (var y = 0; y < halfHeight; ++y)
{
var topOffset = y * bytesPerRow;
var bottomOffset = (height - y - 1) * bytesPerRow;
// make copy of a row on the top half
temp.set(data.subarray(topOffset, topOffset + bytesPerRow));
// copy a row from the bottom half to the top
data.copyWithin(topOffset, bottomOffset, bottomOffset + bytesPerRow);
// copy the copy of the top half row to the bottom half
data.set(temp, bottomOffset);
}
// Create a 2D canvas to store the result
var canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
var context = canvas.getContext('2d');
// Copy the pixels to a 2D canvas
var imageData = context.createImageData(width, height);
imageData.data.set(data);
context.putImageData(imageData, 0, 0);
var re = /(?:\.([^.]+))?$/;
var ext = re.exec(saveimagecache2[url].name)[1];
var name = saveimagecache2[url].name+".png";
if(ext == "png" || ext == "jpg" || ext == "jpeg")
{
var ret = saveimagecache2[url].name.replace('.'+ext,'');
name = ret+".png";
}
console.log("saved texture to blob "+name);
canvas.toBlob(function(blob){objects[name] = blob;},"image/png");
}
})();
(() => {
"use strict";
const Event = class {
constructor(script, target) {
this.script = script;
this.target = target;
this._cancel = false;
this._replace = null;
this._stop = false;
}
preventDefault() {
this._cancel = true;
}
stopPropagation() {
this._stop = true;
}
replacePayload(payload) {
this._replace = payload;
}
};
let callbacks = [];
window.addBeforeScriptExecuteListener = (f) => {
if (typeof f !== "function") {
throw new Error("Event handler must be a function.");
}
callbacks.push(f);
};
window.removeBeforeScriptExecuteListener = (f) => {
let i = callbacks.length;
while (i--) {
if (callbacks[i] === f) {
callbacks.splice(i, 1);
}
}
};
const dispatch = (script, target) => {
if (script.tagName !== "SCRIPT") {
return;
}
const e = new Event(script, target);
if (typeof window.onbeforescriptexecute === "function") {
try {
window.onbeforescriptexecute(e);
} catch (err) {
console.error(err);
}
}
for (const func of callbacks) {
if (e._stop) {
break;
}
try {
func(e);
} catch (err) {
console.error(err);
}
}
if (e._cancel) {
script.textContent = "";
script.remove();
} else if (typeof e._replace === "string") {
script.textContent = e._replace;
}
};
const observer = new MutationObserver((mutations) => {
for (const m of mutations) {
for (const n of m.addedNodes) {
dispatch(n, m.target);
}
}
});
observer.observe(document, {
childList: true,
subtree: true,
});
})();
(() => {
"use strict";
window.onbeforescriptexecute = (e) => {
var links_as_arr = Array.from(e.target.childNodes);
links_as_arr.forEach(function(srimgc)
{
if(srimgc instanceof HTMLScriptElement)
{
if (srimgc.src.indexOf("web/dist/") >= 0 || srimgc.src.indexOf("standaloneViewer") >= 0)
{
e.preventDefault();
e.stopPropagation();
var req = new XMLHttpRequest();
req.open('GET', srimgc.src, false);
req.send('');
var jstext = req.responseText;
var ret = func_RenderLeaf_computed_drawGeometry.exec(jstext);
if (ret)
{
var index1 = ret.index; //+ ret[1].length;
var head1 = jstext.slice(0, index1);
var tail1 = jstext.slice(index1 + ret[0].length);
jstext = head1 + "else{"+ ret[1] +";window.attachbody(this._geometry);}" + tail1;
console.log("[UserScript] Injection: patch_5 injected successful" + srimgc.src);
setTimeout(addbtnfunc, 3000);
}
//ret = func_test.exec(jstext)
var idx = 0;
// while (ret = func_test.exec(jstext))
// {
// var index = ret.index + ret[0].length;
// var head = jstext.slice(0, index);
// var tail = jstext.slice(index);
// jstext = head +"window.attachbody(e);"+ tail;
// //jstext = head + "window.drawhook(e);" + tail;
// func_test.lastIndex = index + 1000;
// console.log("[UserScript] Injection: patch_4 injected successful" + srimgc.src);
// setTimeout(addbtnfunc, 3000);
// }
var obj = document.createElement('script');
obj.type = "text/javascript";
obj.text = jstext;
document.getElementsByTagName('head')[0].appendChild(obj);
}
}
});
};
})();[/I]
Просто выдели все на сцене и нажми cntrl j
Исправленная модель:
// ==UserScript==
// @name SketchfabTextureDownloader
// @version 0.9.1
// @description Download Sketchfab models and/or textures!
// @author shitposting goddess + 20 Jun 2023 page not loading FIX
// @support https://discord.gg/JBJRDB5euG
//@support2 https://discord.gg/Zf2qnNMdgr
// @include /^https?://(www\.)?sketchfab\.com/.*
// @require https://cdnjs.cloudflare.com/ajax/libs/jszip/3.1.5/jszip.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/jszip-utils/0.0.2/jszip-utils.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/1.3.8/FileSaver.js
// @run-at document-start
// @grant unsafeWindow
// @grant GM_download
// ==/UserScript==
var zip = new JSZip();
let folder = zip.folder('collection');
var button_dw = false;
var func_drawGeometry = /(this\._stateCache\.drawGeometry\(this\._graphicContext,t\))/g;
var fund_drawArrays = /t\.drawArrays\(t\.TRIANGLES,0,6\)/g;
//var func_renderInto1 = /x\.renderInto\(n,S,y/g;
var func_renderInto1 = /A\.renderInto\(n,E,R/g; //20 jun 2023 fix
var func_renderInto2 = /g\.renderInto=function\(e,i,r/g;
var func_getResourceImage = /getResourceImage:function\(e,t\){/g;
var func_test = /apply:function\(e\){var t=e instanceof r\.Geometry;/g
var addbtnfunc;
(function() {
'use strict';
var window = unsafeWindow;
console.log("[UserScript]init", window);
window.allmodel = [];
var saveimagecache2 = {};
var objects = {};
var saveimage_to_list = function(url,file_name)
{
if (!saveimagecache2[url])
{
var mdl = {
name: file_name
}
saveimagecache2[url] = mdl;
}
}
addbtnfunc = function() {
var p = document.evaluate("//div[@class='titlebar']", document, null, 9, null).singleNodeValue;
if(p && !button_dw) {
console.log("[UserScript]add btn dwnld");
var btn = document.createElement("a");
btn.setAttribute("class", "control");
btn.innerHTML = "<pre style='font-family:impact;font-size:36px;text-shadow: 1px 1px black;color:#1caad9;'>CLICK TO DOWNLOAD</pre>";
btn.addEventListener('click', () => {
alert('Zipping files...')})
btn.addEventListener("click", dodownload , false);
p.appendChild(btn);
button_dw = true;
} else {
console.log("[UserScript]try add btn later");
setTimeout(addbtnfunc, 3000);
}
}
var dodownload = function() {
console.log("[UserScript]download");
var idx = 0;
window.allmodel.forEach(function(obj)
{
var mdl = {
name: "model_"+idx,
obj:parseobj(obj)
}
console.log(mdl);
dosavefile(mdl);
idx++;
})
PackAll();
}
var PackAll = function ()
{
for (var obj in objects) {
console.log("[UserScript]save file", obj);
folder.file(obj, objects[obj], {binary:true});
}
var file_name = document.getElementsByClassName('model-name__label')[0].textContent;
folder.generateAsync({ type: "blob" }).then(content => saveAs(content, file_name + ".zip"));
}
var parseobj = function(obj)
{
console.log("[UserScript]: obj", obj);
var list = [];
obj._primitives.forEach(function(p) {
if(p && p.indices) {
list.push({
'mode' : p.mode,
'indices' : p.indices._elements
});
}
})
var attr = obj._attributes;
return {
vertex: attr.Vertex._elements,
normal: attr.Normal ? attr.Normal._elements : [],
uv: attr.TexCoord0 ? attr.TexCoord0._elements :
attr.TexCoord1 ? attr.TexCoord1._elements :
attr.TexCoord2 ? attr.TexCoord2._elements :
attr.TexCoord2 ? attr.TexCoord2._elements :
attr.TexCoord3 ? attr.TexCoord3._elements :
attr.TexCoord4 ? attr.TexCoord4._elements :
attr.TexCoord5 ? attr.TexCoord5._elements :
attr.TexCoord6 ? attr.TexCoord6._elements :
attr.TexCoord7 ? attr.TexCoord7._elements :
attr.TexCoord8 ? attr.TexCoord8._elements : [],
primitives: list,
};
}
var dosavefile = function(mdl)
{
var obj = mdl.obj;
//console.log("TEST");
//console.log(obj);
var str = '';
str += 'mtllib ' + mdl.name + '.mtl\n';
str += 'o ' + mdl.name + '\n';
for (var i = 0; i < obj.vertex.length; i += 3) {
str += 'v ';
for (var j = 0; j < 3; ++j) {
str += obj.vertex[i + j] + ' ';
}
str += '\n';
}
for (i = 0; i < obj.normal.length; i += 3) {
str += 'vn ';
for (j = 0; j < 3; ++j) {
str += obj.normal[i + j] + ' ';
}
str += '\n';
}
for (i = 0; i < obj.uv.length; i += 2) {
str += 'vt ';
for (j = 0; j < 2; ++j) {
str += obj.uv[i + j] + ' ';
}
str += '\n';
}
//str += 'usemtl ' + mdl.name + '\n';
str += 's on \n';
var vn = obj.normal.length != 0;
var vt = obj.uv.length != 0;
for (i = 0; i < obj.primitives.length; ++i) {
var primitive = obj.primitives[i];
if (primitive.mode == 4 || primitive.mode == 5) {
var strip = (primitive.mode == 5);
for (j = 0; j + 2 < primitive.indices.length; !strip ? j += 3 : j++) {
str += 'f ';
var order = [ 0, 1, 2];
if (strip && (j % 2 == 1)) {
order = [ 0, 2, 1];
}
for (var k = 0; k < 3; ++k)
{
var faceNum = primitive.indices[j + order[k]] + 1;
str += faceNum;
if (vn || vt) {
str += '/';
if (vt) {
str += faceNum;
}
if (vn) {
str += '/' + faceNum;
}
}
str += ' ';
}
str += '\n';
}
}
else {
console.log("[UserScript]dosavefile: unknown primitive mode", primitive);
}
}
str += '\n';
var objblob = new Blob([str], {type:'text/plain'});
objects[mdl.name+".obj"] = objblob;
}
window.attachbody = function(obj)
{
if(obj._faked != true && ((obj.stateset && obj.stateset._name) || obj._name || (obj._parents && obj._parents[0]._name)) ) {
obj._faked = true;
if(obj._name == "composer layer" || obj._name == "Ground - Geometry") return;
window.allmodel.push(obj)
console.log(obj);
}
//console.log(obj);
}
window.hook_test = function(e, idx)
{
console.log("hooked index: "+idx);
console.log(e);
}
window.drawhookcanvas = function(e, imagemodel)
{
if((e.width == 128 && e.height == 128) || (e.width == 32 && e.height == 32) || (e.width == 64 && e.height == 64))
{
return e;
}
if(imagemodel)
{
var alpha = e.options.format;
var filename_image = imagemodel.attributes.name;
var uid = imagemodel.attributes.uid;
var url_image = e.url;
var max_size = 0;
var obr = e;
imagemodel.attributes.images.forEach(function(img)
{
var alpha_is_check = alpha == "A" ? img.options.format == alpha : true;
var d = img.width;
while ( d % 2 == 0 )
{
d = d / 2;
}
if(img.size > max_size && alpha_is_check && d == 1)
{
max_size = img.size;
url_image = img.url;
uid = img.uid;
obr = img;
}
});
if(!saveimagecache2[url_image])
{
console.log(e);
saveimage_to_list(url_image, filename_image);
}
else
{
//console.log(e);
}
return obr;
}
return e;
}
window.drawhookimg = function(gl,t)
{
console.log(JSON.stringify(t));
var url = t[5].currentSrc;
var width = t[5].width;
var height = t[5].height;
if(!saveimagecache2[url])
{
//console.log("rejected:"+url);
return;
}
else
{
//console.log("saved texture:"+url);
}
var data = new Uint8Array(width * height * 4);
gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, data);
var halfHeight = height / 2 | 0; // the | 0 keeps the result an int
var bytesPerRow = width * 4;
// make a temp buffer to hold one row
var temp = new Uint8Array(width * 4);
for (var y = 0; y < halfHeight; ++y)
{
var topOffset = y * bytesPerRow;
var bottomOffset = (height - y - 1) * bytesPerRow;
// make copy of a row on the top half
temp.set(data.subarray(topOffset, topOffset + bytesPerRow));
// copy a row from the bottom half to the top
data.copyWithin(topOffset, bottomOffset, bottomOffset + bytesPerRow);
// copy the copy of the top half row to the bottom half
data.set(temp, bottomOffset);
}
// Create a 2D canvas to store the result
var canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
var context = canvas.getContext('2d');
// Copy the pixels to a 2D canvas
var imageData = context.createImageData(width, height);
imageData.data.set(data);
context.putImageData(imageData, 0, 0);
var re = /(?:\.([^.]+))?$/;
var ext = re.exec(saveimagecache2[url].name)[1];
var name = saveimagecache2[url].name+".png";
if(ext == "png" || ext == "jpg" || ext == "jpeg")
{
var ret = saveimagecache2[url].name.replace('.'+ext,'');
name = ret+".png";
}
console.log("saved texture to blob "+name);
canvas.toBlob(function(blob){objects[name] = blob;},"image/png");
}
})();
(() => {
"use strict";
const Event = class {
constructor(script, target) {
this.script = script;
this.target = target;
this._cancel = false;
this._replace = null;
this._stop = false;
}
preventDefault() {
this._cancel = true;
}
stopPropagation() {
this._stop = true;
}
replacePayload(payload) {
this._replace = payload;
}
};
let callbacks = [];
window.addBeforeScriptExecuteListener = (f) => {
if (typeof f !== "function") {
throw new Error("Event handler must be a function.");
}
callbacks.push(f);
};
window.removeBeforeScriptExecuteListener = (f) => {
let i = callbacks.length;
while (i--) {
if (callbacks[i] === f) {
callbacks.splice(i, 1);
}
}
};
const dispatch = (script, target) => {
if (script.tagName !== "SCRIPT") {
return;
}
const e = new Event(script, target);
if (typeof window.onbeforescriptexecute === "function") {
try {
window.onbeforescriptexecute(e);
} catch (err) {
console.error(err);
}
}
for (const func of callbacks) {
if (e._stop) {
break;
}
try {
func(e);
} catch (err) {
console.error(err);
}
}
if (e._cancel) {
script.textContent = "";
script.remove();
} else if (typeof e._replace === "string") {
script.textContent = e._replace;
}
};
const observer = new MutationObserver((mutations) => {
for (const m of mutations) {
for (const n of m.addedNodes) {
dispatch(n, m.target);
}
}
});
observer.observe(document, {
childList: true,
subtree: true,
});
})();
(() => {
"use strict";
window.onbeforescriptexecute = (e) => {
var links_as_arr = Array.from(e.target.childNodes);
links_as_arr.forEach(function(srimgc)
{
if(srimgc instanceof HTMLScriptElement)
{
if (srimgc.src.indexOf("web/dist/") >= 0 || srimgc.src.indexOf("standaloneViewer") >= 0)
{
e.preventDefault();
e.stopPropagation();
var req = new XMLHttpRequest();
req.open('GET', srimgc.src, false);
req.send('');
var jstext = req.responseText;
var ret = func_renderInto1.exec(jstext);
if (ret)
{
var index = ret.index + ret[0].length;
var head = jstext.slice(0, index);
var tail = jstext.slice(index);
jstext = head + ",i" + tail;
console.log("[UserScript] Injection: patch_0 injected successful " + srimgc.src);
}
ret = func_renderInto2.exec(jstext);
if (ret)
{
var index = ret.index + ret[0].length;
var head = jstext.slice(0, index);
var tail = jstext.slice(index);
jstext = head + ",image_data" + tail;
console.log("[UserScript] Injection: patch_1 injected successful " + srimgc.src);
if (!func_renderInto1.exec(jstext))
console.log("[UserScript] But patch_0 failed " + srimgc.src);
}
ret = fund_drawArrays.exec(jstext);
if (ret)
{
var index = ret.index + ret[0].length;
var head = jstext.slice(0, index);
var tail = jstext.slice(index);
jstext = head + ",window.drawhookimg(t,image_data)" + tail;
console.log("[UserScript] Injection: patch_2 injected successful " + srimgc.src);
}
ret = func_getResourceImage.exec(jstext);
if (ret)
{
var index = ret.index + ret[0].length;
var head = jstext.slice(0, index);
var tail = jstext.slice(index);
jstext = head + "e = window.drawhookcanvas(e,this._imageModel);" + tail;
console.log("[UserScript] Injection: patch_3 injected successful " + srimgc.src);
}
ret = func_drawGeometry.exec(jstext);
if (ret)
{
var index1 = ret.index + ret[1].length;
var head1 = jstext.slice(0, index1);
var tail1 = jstext.slice(index1);
jstext = head1 + ";window.attachbody(t);" + tail1;
console.log("[UserScript] Injection: patch_4 injected successful " + srimgc.src);
setTimeout(addbtnfunc, 3000);
}
//ret = func_test.exec(jstext)
var idx = 0;
// while (ret = func_test.exec(jstext))
// {
// var index = ret.index + ret[0].length;
// var head = jstext.slice(0, index);
// var tail = jstext.slice(index);
// jstext = head +"window.attachbody(e);"+ tail;
// //jstext = head + "window.drawhook(e);" + tail;
// func_test.lastIndex = index + 1000;
// console.log("[UserScript] Injection: patch_4 injected successful" + srimgc.src);
// setTimeout(addbtnfunc, 3000);
// }
var obj = document.createElement('script');
obj.type = "text/javascript";
obj.text = jstext;
document.getElementsByTagName('head')[0].appendChild(obj);
}
}
});
};
})();
Привет, tewi3 ! Огромное спасибо за подсказку. Действительно сработало! Удачи!Скиньте модели которые у вас не получается рипнуть, я попробую достать их.
Я вот Шольца уже рипнул при помощи скрипта из архива
Посмотреть вложение 265687
Пожалуйста, авторизуйтесь для просмотра ссылки.Сам скрипт (я использовал браузер firefox и версию tampermonkey 4.18.0):
Установку расширения надо проводить в самом браузере, тогда она пройдет автоматически при нажатии кнопки загрузить файл
Пожалуйста, авторизуйтесь для просмотра ссылки.
Не подгружались модели. Этот скрипт сработалЕсли у кого-то не работает скрипт Web Ripper V0.9 fix sunkid, то попробуйте этот (этот скрипт сразу выкачивает и модель, и текстуры):
Если что все скрипты для браузера не поддерживают модели с большим количеством полигонов, например как эта:JavaScript:// ==UserScript== // @name SketchfabTextureDownloader // @version 0.9.1 // @description Download Sketchfab models and/or textures! // @author shitposting goddess + 20 Jun 2023 page not loading FIX // @support https://discord.gg/JBJRDB5euG //@support2 https://discord.gg/Zf2qnNMdgr // @include /^https?://(www\.)?sketchfab\.com/.* // @require https://cdnjs.cloudflare.com/ajax/libs/jszip/3.1.5/jszip.min.js // @require https://cdnjs.cloudflare.com/ajax/libs/jszip-utils/0.0.2/jszip-utils.min.js // @require https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/1.3.8/FileSaver.js // @run-at document-start // @grant unsafeWindow // @grant GM_download // ==/UserScript== var zip = new JSZip(); let folder = zip.folder('collection'); var button_dw = false; var func_drawGeometry = /(this\._stateCache\.drawGeometry\(this\._graphicContext,t\))/g; var fund_drawArrays = /t\.drawArrays\(t\.TRIANGLES,0,6\)/g; //var func_renderInto1 = /x\.renderInto\(n,S,y/g; var func_renderInto1 = /A\.renderInto\(n,E,R/g; //20 jun 2023 fix var func_renderInto2 = /g\.renderInto=function\(e,i,r/g; var func_getResourceImage = /getResourceImage:function\(e,t\){/g; var func_test = /apply:function\(e\){var t=e instanceof r\.Geometry;/g var addbtnfunc; (function() { 'use strict'; var window = unsafeWindow; console.log("[UserScript]init", window); window.allmodel = []; var saveimagecache2 = {}; var objects = {}; var saveimage_to_list = function(url,file_name) { if (!saveimagecache2[url]) { var mdl = { name: file_name } saveimagecache2[url] = mdl; } } addbtnfunc = function() { var p = document.evaluate("//div[@class='titlebar']", document, null, 9, null).singleNodeValue; if(p && !button_dw) { console.log("[UserScript]add btn dwnld"); var btn = document.createElement("a"); btn.setAttribute("class", "control"); btn.innerHTML = "<pre style='font-family:impact;font-size:36px;text-shadow: 1px 1px black;color:#1caad9;'>CLICK TO DOWNLOAD</pre>"; btn.addEventListener('click', () => { alert('Zipping files...')}) btn.addEventListener("click", dodownload , false); p.appendChild(btn); button_dw = true; } else { console.log("[UserScript]try add btn later"); setTimeout(addbtnfunc, 3000); } } var dodownload = function() { console.log("[UserScript]download"); var idx = 0; window.allmodel.forEach(function(obj) { var mdl = { name: "model_"+idx, obj:parseobj(obj) } console.log(mdl); dosavefile(mdl); idx++; }) PackAll(); } var PackAll = function () { for (var obj in objects) { console.log("[UserScript]save file", obj); folder.file(obj, objects[obj], {binary:true}); } var file_name = document.getElementsByClassName('model-name__label')[0].textContent; folder.generateAsync({ type: "blob" }).then(content => saveAs(content, file_name + ".zip")); } var parseobj = function(obj) { console.log("[UserScript]: obj", obj); var list = []; obj._primitives.forEach(function(p) { if(p && p.indices) { list.push({ 'mode' : p.mode, 'indices' : p.indices._elements }); } }) var attr = obj._attributes; return { vertex: attr.Vertex._elements, normal: attr.Normal ? attr.Normal._elements : [], uv: attr.TexCoord0 ? attr.TexCoord0._elements : attr.TexCoord1 ? attr.TexCoord1._elements : attr.TexCoord2 ? attr.TexCoord2._elements : attr.TexCoord2 ? attr.TexCoord2._elements : attr.TexCoord3 ? attr.TexCoord3._elements : attr.TexCoord4 ? attr.TexCoord4._elements : attr.TexCoord5 ? attr.TexCoord5._elements : attr.TexCoord6 ? attr.TexCoord6._elements : attr.TexCoord7 ? attr.TexCoord7._elements : attr.TexCoord8 ? attr.TexCoord8._elements : [], primitives: list, }; } var dosavefile = function(mdl) { var obj = mdl.obj; //console.log("TEST"); //console.log(obj); var str = ''; str += 'mtllib ' + mdl.name + '.mtl\n'; str += 'o ' + mdl.name + '\n'; for (var i = 0; i < obj.vertex.length; i += 3) { str += 'v '; for (var j = 0; j < 3; ++j) { str += obj.vertex[i + j] + ' '; } str += '\n'; } for (i = 0; i < obj.normal.length; i += 3) { str += 'vn '; for (j = 0; j < 3; ++j) { str += obj.normal[i + j] + ' '; } str += '\n'; } for (i = 0; i < obj.uv.length; i += 2) { str += 'vt '; for (j = 0; j < 2; ++j) { str += obj.uv[i + j] + ' '; } str += '\n'; } //str += 'usemtl ' + mdl.name + '\n'; str += 's on \n'; var vn = obj.normal.length != 0; var vt = obj.uv.length != 0; for (i = 0; i < obj.primitives.length; ++i) { var primitive = obj.primitives[i]; if (primitive.mode == 4 || primitive.mode == 5) { var strip = (primitive.mode == 5); for (j = 0; j + 2 < primitive.indices.length; !strip ? j += 3 : j++) { str += 'f '; var order = [ 0, 1, 2]; if (strip && (j % 2 == 1)) { order = [ 0, 2, 1]; } for (var k = 0; k < 3; ++k) { var faceNum = primitive.indices[j + order[k]] + 1; str += faceNum; if (vn || vt) { str += '/'; if (vt) { str += faceNum; } if (vn) { str += '/' + faceNum; } } str += ' '; } str += '\n'; } } else { console.log("[UserScript]dosavefile: unknown primitive mode", primitive); } } str += '\n'; var objblob = new Blob([str], {type:'text/plain'}); objects[mdl.name+".obj"] = objblob; } window.attachbody = function(obj) { if(obj._faked != true && ((obj.stateset && obj.stateset._name) || obj._name || (obj._parents && obj._parents[0]._name)) ) { obj._faked = true; if(obj._name == "composer layer" || obj._name == "Ground - Geometry") return; window.allmodel.push(obj) console.log(obj); } //console.log(obj); } window.hook_test = function(e, idx) { console.log("hooked index: "+idx); console.log(e); } window.drawhookcanvas = function(e, imagemodel) { if((e.width == 128 && e.height == 128) || (e.width == 32 && e.height == 32) || (e.width == 64 && e.height == 64)) { return e; } if(imagemodel) { var alpha = e.options.format; var filename_image = imagemodel.attributes.name; var uid = imagemodel.attributes.uid; var url_image = e.url; var max_size = 0; var obr = e; imagemodel.attributes.images.forEach(function(img) { var alpha_is_check = alpha == "A" ? img.options.format == alpha : true; var d = img.width; while ( d % 2 == 0 ) { d = d / 2; } if(img.size > max_size && alpha_is_check && d == 1) { max_size = img.size; url_image = img.url; uid = img.uid; obr = img; } }); if(!saveimagecache2[url_image]) { console.log(e); saveimage_to_list(url_image, filename_image); } else { //console.log(e); } return obr; } return e; } window.drawhookimg = function(gl,t) { console.log(JSON.stringify(t)); var url = t[5].currentSrc; var width = t[5].width; var height = t[5].height; if(!saveimagecache2[url]) { //console.log("rejected:"+url); return; } else { //console.log("saved texture:"+url); } var data = new Uint8Array(width * height * 4); gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, data); var halfHeight = height / 2 | 0; // the | 0 keeps the result an int var bytesPerRow = width * 4; // make a temp buffer to hold one row var temp = new Uint8Array(width * 4); for (var y = 0; y < halfHeight; ++y) { var topOffset = y * bytesPerRow; var bottomOffset = (height - y - 1) * bytesPerRow; // make copy of a row on the top half temp.set(data.subarray(topOffset, topOffset + bytesPerRow)); // copy a row from the bottom half to the top data.copyWithin(topOffset, bottomOffset, bottomOffset + bytesPerRow); // copy the copy of the top half row to the bottom half data.set(temp, bottomOffset); } // Create a 2D canvas to store the result var canvas = document.createElement('canvas'); canvas.width = width; canvas.height = height; var context = canvas.getContext('2d'); // Copy the pixels to a 2D canvas var imageData = context.createImageData(width, height); imageData.data.set(data); context.putImageData(imageData, 0, 0); var re = /(?:\.([^.]+))?$/; var ext = re.exec(saveimagecache2[url].name)[1]; var name = saveimagecache2[url].name+".png"; if(ext == "png" || ext == "jpg" || ext == "jpeg") { var ret = saveimagecache2[url].name.replace('.'+ext,''); name = ret+".png"; } console.log("saved texture to blob "+name); canvas.toBlob(function(blob){objects[name] = blob;},"image/png"); } })(); (() => { "use strict"; const Event = class { constructor(script, target) { this.script = script; this.target = target; this._cancel = false; this._replace = null; this._stop = false; } preventDefault() { this._cancel = true; } stopPropagation() { this._stop = true; } replacePayload(payload) { this._replace = payload; } }; let callbacks = []; window.addBeforeScriptExecuteListener = (f) => { if (typeof f !== "function") { throw new Error("Event handler must be a function."); } callbacks.push(f); }; window.removeBeforeScriptExecuteListener = (f) => { let i = callbacks.length; while (i--) { if (callbacks[i] === f) { callbacks.splice(i, 1); } } }; const dispatch = (script, target) => { if (script.tagName !== "SCRIPT") { return; } const e = new Event(script, target); if (typeof window.onbeforescriptexecute === "function") { try { window.onbeforescriptexecute(e); } catch (err) { console.error(err); } } for (const func of callbacks) { if (e._stop) { break; } try { func(e); } catch (err) { console.error(err); } } if (e._cancel) { script.textContent = ""; script.remove(); } else if (typeof e._replace === "string") { script.textContent = e._replace; } }; const observer = new MutationObserver((mutations) => { for (const m of mutations) { for (const n of m.addedNodes) { dispatch(n, m.target); } } }); observer.observe(document, { childList: true, subtree: true, }); })(); (() => { "use strict"; window.onbeforescriptexecute = (e) => { var links_as_arr = Array.from(e.target.childNodes); links_as_arr.forEach(function(srimgc) { if(srimgc instanceof HTMLScriptElement) { if (srimgc.src.indexOf("web/dist/") >= 0 || srimgc.src.indexOf("standaloneViewer") >= 0) { e.preventDefault(); e.stopPropagation(); var req = new XMLHttpRequest(); req.open('GET', srimgc.src, false); req.send(''); var jstext = req.responseText; var ret = func_renderInto1.exec(jstext); if (ret) { var index = ret.index + ret[0].length; var head = jstext.slice(0, index); var tail = jstext.slice(index); jstext = head + ",i" + tail; console.log("[UserScript] Injection: patch_0 injected successful " + srimgc.src); } ret = func_renderInto2.exec(jstext); if (ret) { var index = ret.index + ret[0].length; var head = jstext.slice(0, index); var tail = jstext.slice(index); jstext = head + ",image_data" + tail; console.log("[UserScript] Injection: patch_1 injected successful " + srimgc.src); if (!func_renderInto1.exec(jstext)) console.log("[UserScript] But patch_0 failed " + srimgc.src); } ret = fund_drawArrays.exec(jstext); if (ret) { var index = ret.index + ret[0].length; var head = jstext.slice(0, index); var tail = jstext.slice(index); jstext = head + ",window.drawhookimg(t,image_data)" + tail; console.log("[UserScript] Injection: patch_2 injected successful " + srimgc.src); } ret = func_getResourceImage.exec(jstext); if (ret) { var index = ret.index + ret[0].length; var head = jstext.slice(0, index); var tail = jstext.slice(index); jstext = head + "e = window.drawhookcanvas(e,this._imageModel);" + tail; console.log("[UserScript] Injection: patch_3 injected successful " + srimgc.src); } ret = func_drawGeometry.exec(jstext); if (ret) { var index1 = ret.index + ret[1].length; var head1 = jstext.slice(0, index1); var tail1 = jstext.slice(index1); jstext = head1 + ";window.attachbody(t);" + tail1; console.log("[UserScript] Injection: patch_4 injected successful " + srimgc.src); setTimeout(addbtnfunc, 3000); } //ret = func_test.exec(jstext) var idx = 0; // while (ret = func_test.exec(jstext)) // { // var index = ret.index + ret[0].length; // var head = jstext.slice(0, index); // var tail = jstext.slice(index); // jstext = head +"window.attachbody(e);"+ tail; // //jstext = head + "window.drawhook(e);" + tail; // func_test.lastIndex = index + 1000; // console.log("[UserScript] Injection: patch_4 injected successful" + srimgc.src); // setTimeout(addbtnfunc, 3000); // } var obj = document.createElement('script'); obj.type = "text/javascript"; obj.text = jstext; document.getElementsByTagName('head')[0].appendChild(obj); } } }); }; })();
Пожалуйста, авторизуйтесь для просмотра ссылки.
Есть предложения как рипать такие большие модели без проги от tracerx?
В мозилле недавно работал,все скачивалосьРебят в яндекс браузере веб риппер вообще не фурычит (мб ток у меня так), заработал в хроме V3 для скачки и V3 для текстур работают, но только столкнулся с тем что obj файлик без материалов и uv как будто не соответствует текстурам, печаль, придётся ручками править
Если не скачивает текстуры, то на модели их либо нет. Либо она не до конца подгружена. Чтобы скачались все текстуры нужно ждать когда эта синяя полоска доползет до концау меня не скачиваються текстуры, модель скачивается, а вот текстуры нет, что делать?
Значит нормальную модель с большим количеством полигонов не скачаешь?В хроме работает, но не все модели качает, я так понимаю ограничение на количество полигонов.
Я качаю через Tumpetmonkey, и обратил внимание, что если не дожидаться загрузки модели полностью (голубая полоска вверху экрана), то рип захватывает не все текстуры, а порой и не все меши.у меня не скачиваються текстуры, модель скачивается, а вот текстуры нет, что делать?
Нет ,я уже пробовал, веб скриптом не получается, зависает на стадии отображения модели и все.Значит нормальную модель с большим количеством полигонов не скачаешь?
Нормальную модельку , правда без текстур только приложением качать, там можно любое количество полигонов, качал в основном модели под 3д печать.Значит нормальную модель с большим количеством полигонов не скачаешь?
Подскажите, каким приложением? тоже столкнулся с проблемой, не могу выкачать 3д скан нивы, 4кк полигоновНормальную модельку , правда без текстур только приложением качать, там можно любое количество полигонов, качал в основном модели под 3д печать.
Проект предоставляет различный материал, относящийся к сфере киберспорта, программирования, ПО для игр, а также позволяет его участникам общаться на многие другие темы. Почта для жалоб: admin@yougame.biz