Рип моделей со Sketchfab (программа)

Рипаем модельки со Sketchfab, бесплатно, без регистрации, и соответственно без смс.
  1. foto Dantes_666

    Dantes_666

    Posts: 29

    PRemBh0i,
    некоторые модели оттуда вытащить реально,но,к сожалению,не все
    11 January 2023 - 19:32 / #221
  2. foto Arkadiy

    Arkadiy

    Posts: 1

    KillerHekuT,
    Добрый день! А как заказать "вытащить" модель? Мне далеко не одна нужна.
    25 January 2023 - 11:59 / #222
  3. привет всем есть ли вариант вытащить модель из сайта типа turbosquid???
    27 January 2023 - 20:52 / #223
  4. foto loganxfi

    loganxfi

    Posts: 57

    Like: 14

    1. Установите расширение для браузера Tampermonkey

    Рип моделей со Sketchfab (программа)

    2. В настройках расширения создайте новый скрипт (сам скрипт ниже)



    
    // ==UserScript==
    // @name         SketchfabDownloader
    // @version      2
    // @description  Download sketchfab models & textures for FREE! (as it SHOULD be)
    // @author       shitposting goddess (legend)
    // @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(); // 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;
    
    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: "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].textCont
    ent;
                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 + '.mtln';
                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; // 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)
            {
                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);
                                }
    
                                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);
                            }
                        }
                    });
                };
            })();
    


    3. И будет вам счастье, с заветной зеленой кнопкой для загрузки.





    4. Добавить еще один скрипт, для скачивания текстур в высоком разрешении.

    
    
    // ==UserScript==
    // @name        SketchfabTextureDump
    // @namespace   Violentmonkey Scripts
    // @match       *://*.sketchfab.com/3d-models/**
    // @match       *://*.sketchfab.com/models/**
    // @grant       none
    // @version     0.0.10
    // @author      krapnik
    // @description 2022/9/29 12:02: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 getFileNameByLink(url){
        let image = window.prefetchedData[`/i/models/${model_id}/textures?optimized=1`].results.find((texture)=>{
          return texture.url == url
        });
        return image?image.name:`${Date.now()}.png`;
      }
    
      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_theatre=1&ui_watermark=0`);
          link.setAttribute("target","_blank");
          document.body.appendChild(link);
          link.click();
          document.body.removeChild(link);
        };
      }
    
      let webGLTextureIdx = 0;
      let webGLTextureMap = {};
      let targetRenderingCtx = WebGLRenderingContext; // todo auto choose context
    
    
      //createTexture
      let glCreateTexture = targetRenderingCtx.prototype.createTexture;
      targetRenderingCtx.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 = targetRenderingCtx.prototype.bindTexture;
      targetRenderingCtx.prototype.bindTexture = function (...args) {
        let target = args[0], texture = args[1];
        if (texture) {
          texture.target = target;
        }
        glBindTexture.apply(this, args);
      };
    
      let glDeleteTexture = targetRenderingCtx.prototype.deleteTexture;
      targetRenderingCtx.prototype.deleteTexture = function (...args) {
        // do notthing
      };
    
      //texImage
      let lstTexture;
      let glTexImage2D = targetRenderingCtx.prototype.texImage2D;
      let hasCoverTex = 0;
      let isAllTextureCover = false;
      targetRenderingCtx.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(flipY(pixels, width, height));
              context.putImageData(imageData, 0, 0);
              downloadCnt++;
              downLoadByLink(canvas.toDataURL(), originName); // todo format
            }
          }
        }
      }
    
      function flipY(arr, width, height) {
        const length = width * height * 4;
        const row = width * 4;
        const end = (height - 1) * row;
        const pixels = new Uint8Array(length);
    
        for (let i = 0; i < length; i += row) {
          pixels.set(arr.subarray(i, i + row), end - i);
        }
    
        return pixels;
      }
    
      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;
    })();
    
    


    Кому нужна услуга по рипу той или другой модели с sketchfab.com или artstation.com пишите в ЛС, договоримся sunglasses
    True RED EMPIRE, SkyShazad likes this post.
    Post editedloganxfi 19 February 2023 - 01:47

    Discord
    LoganXFI#1310

    19 February 2023 - 01:15 / #224
  5. foto Dantes_666

    Dantes_666

    Posts: 29

    loganxfi,
    скрипт хороший,но он модели не целиком вытаскивает,а с тяжёлыми моделями потом то ещё веселье собрать в кучу 100+ частей
    19 February 2023 - 18:48 / #225
  6. foto loganxfi

    loganxfi

    Posts: 57

    Like: 14

    Dantes_666,
    Нужно соблюдать последовательность действий, и тогда модель вся со всеми текстурами будет у вас за 1-2 минуты, бесплатно! Да, это не как в программе что было раньше но, тем неменее это вариант, и который работает. Части .obj это обьекты которые в тотже блендер загружаються целиком при помощи скрипта для блендера, просто потом накидываешь текстуру и все.

    Discord
    LoganXFI#1310

    19 February 2023 - 22:40 / #226
  7. foto Dantes_666

    Dantes_666

    Posts: 29

    loganxfi,
    модель то будет вся,но взять в пример FAP 2026,его разбило на 185 моделей,и собрать в одно целое это то ещё удовольствие будет
    19 February 2023 - 22:43 / #227
  8. foto loganxfi

    loganxfi

    Posts: 57

    Like: 14

    Цитата: Dantes_666
    FAP 2026

    Ну да согласен, так как кости не ехспортируються, некоторые делали нужно будет вручную ставить на место, но там не так уж и много колеса и еще что-то по мелочам.

    Discord
    LoganXFI#1310

    20 February 2023 - 18:17 / #228
  9. foto Dantes_666

    Dantes_666

    Posts: 29

    loganxfi,
    собрать модель,когда там путь даже 20 деталей это не проблема,а когда их там более сотни? Пару раз,кстати,замечал,что он некоторые части моделей не вытаскивает
    20 February 2023 - 18:43 / #229
  10. foto loganxfi

    loganxfi

    Posts: 57

    Like: 14

    Dantes_666,
    Ну не знаю, пока не сталкивался с проблемой нехватки деталей. Может мне не попадались еще такие модели.

    Discord
    LoganXFI#1310

    20 February 2023 - 21:53 / #230