@@ -43,6 +43,7 @@ const loadedTextureCache = {};
4343const modelInstances = { } ;
4444
4545const textureCache = { } ;
46+ const canvasCache = { } ;
4647const materialCache = { } ;
4748const geometryCache = { } ;
4849const instanceCache = { } ;
@@ -449,10 +450,11 @@ let renderModel = function (modelRender, model, textures, textureNames, type, na
449450 false ,
450451 false ,
451452 false ) ;
452- cachedInstance = instanceCache [ modelKey ] = {
453+ cachedInstance = {
453454 instance : newInstance ,
454455 index : 0
455456 } ;
457+ instanceCache [ modelKey ] = cachedInstance ;
456458 let _v3o = new THREE . Vector3 ( ) ;
457459 let _v3s = new THREE . Vector3 ( 1 , 1 , 1 ) ;
458460 let _q = new THREE . Quaternion ( ) ;
@@ -474,6 +476,7 @@ let renderModel = function (modelRender, model, textures, textureNames, type, na
474476 } ;
475477
476478 if ( instanceCache . hasOwnProperty ( modelKey ) ) {
479+ console . debug ( "Using cached model instance (" + modelKey + ")" ) ;
477480 let cachedInstance = instanceCache [ modelKey ] ;
478481 applyModelTransforms ( cachedInstance . instance , cachedInstance . index ++ ) ;
479482 return ;
@@ -513,9 +516,10 @@ let renderModel = function (modelRender, model, textures, textureNames, type, na
513516 } ;
514517
515518 promises . push ( new Promise ( ( resolve ) => {
519+ let baseName = name . replaceAll ( " " , "_" ) . replaceAll ( "-" , "_" ) . toLowerCase ( ) + "_" + ( element . __comment ? element . __comment . replaceAll ( " " , "_" ) . replaceAll ( "-" , "_" ) . toLowerCase ( ) + "_" : "" ) ;
516520 createCube ( element . to [ 0 ] - element . from [ 0 ] , element . to [ 1 ] - element . from [ 1 ] , element . to [ 2 ] - element . from [ 2 ] ,
517- name . replaceAll ( " " , "_" ) . replaceAll ( "-" , "_" ) . toLowerCase ( ) + "_" + ( element . __comment ? element . __comment . replaceAll ( " " , "_" ) . replaceAll ( "-" , "_" ) . toLowerCase ( ) + "_" : "" ) + Date . now ( ) ,
518- element . faces , fallbackFaces , textures , textureNames , modelRender . options . assetRoot )
521+ baseName + Date . now ( ) ,
522+ element . faces , fallbackFaces , textures , textureNames , modelRender . options . assetRoot , baseName )
519523 . then ( ( cube ) => {
520524 cube . applyMatrix ( new THREE . Matrix4 ( ) . makeTranslation ( ( element . to [ 0 ] - element . from [ 0 ] ) / 2 , ( element . to [ 1 ] - element . from [ 1 ] ) / 2 , ( element . to [ 2 ] - element . from [ 2 ] ) / 2 ) ) ;
521525 cube . applyMatrix ( new THREE . Matrix4 ( ) . makeTranslation ( element . from [ 0 ] , element . from [ 1 ] , element . from [ 2 ] ) ) ;
@@ -661,7 +665,7 @@ let createPlane = function (name, textures) {
661665
662666
663667/// From https://github.com/InventivetalentDev/SkinRender/blob/master/js/render/skin.js#L353
664- let createCube = function ( width , height , depth , name , faces , fallbackFaces , textures , textureNames , assetRoot ) {
668+ let createCube = function ( width , height , depth , name , faces , fallbackFaces , textures , textureNames , assetRoot , baseName ) {
665669 return new Promise ( ( resolve ) => {
666670 let geometryKey = width + "_" + height + "_" + depth ;
667671 let geometry ;
@@ -699,12 +703,9 @@ let createCube = function (width, height, depth, name, faces, fallbackFaces, tex
699703 return ;
700704 }
701705
702- let img = new Image ( ) ;
703- img . onerror = function ( err ) {
704- console . warn ( err ) ;
705- resolve ( null ) ;
706- } ;
707- img . onload = function ( ) {
706+ let canvasKey = textureRef + "_" + f + "_" + baseName ;
707+
708+ let processImgToCanvasData = ( img ) => {
708709 let uv = face . uv ;
709710 if ( ! uv ) {
710711 // console.warn("Missing UV mapping for face " + f + " in model " + name + ". Using defaults");
@@ -753,9 +754,29 @@ let createCube = function (width, height, depth, name, faces, fallbackFaces, tex
753754 }
754755 }
755756
757+ let dataUrl = canvas . toDataURL ( "image/png" ) ;
758+ let dataHash = md5 ( dataUrl ) ;
759+
760+ let d = {
761+ data : canvasData ,
762+ dataUrl : dataUrl ,
763+ dataUrlHash : dataHash ,
764+ hasTransparency : hasTransparency ,
765+ width : canvas . width ,
766+ height : canvas . height
767+ } ;
768+ console . debug ( "Caching new canvas (" + canvasKey + "/" + dataHash + ")" )
769+ canvasCache [ canvasKey ] = d ;
770+ return d ;
771+ } ;
772+
773+ let loadTextureFromCanvas = ( canvas ) => {
774+
775+
756776 let loadTextureDefault = function ( canvas ) {
757- let data = canvas . toDataURL ( "image/png" ) ;
758- let hash = md5 ( data ) ;
777+ let data = canvas . dataUrl ;
778+ let hash = canvas . dataUrlHash ;
779+ let hasTransparency = canvas . hasTransparency ;
759780
760781 if ( materialCache . hasOwnProperty ( hash ) ) { // Use material from cache
761782 console . debug ( "Using cached Material (" + hash + ")" ) ;
@@ -812,6 +833,7 @@ let createCube = function (width, height, depth, name, faces, fallbackFaces, tex
812833 } ;
813834
814835 let loadTextureWithMeta = function ( canvas , meta ) {
836+ let hasTransparency = canvas . hasTransparency ;
815837 let frametime = 1 ;
816838 if ( meta . hasOwnProperty ( "animation" ) ) {
817839 if ( meta . animation . hasOwnProperty ( "frametime" ) ) {
@@ -903,8 +925,42 @@ let createCube = function (width, height, depth, name, faces, fallbackFaces, tex
903925 loadTextureDefault ( canvas ) ;
904926 }
905927 } ;
906- img . src = textures [ textureRef ] ;
907928
929+
930+ if ( canvasCache . hasOwnProperty ( canvasKey ) ) {
931+ let cachedCanvas = canvasCache [ canvasKey ] ;
932+
933+ if ( cachedCanvas . hasOwnProperty ( "img" ) ) {
934+ console . debug ( "Waiting for canvas image that's already loading (" + canvasKey + ")" )
935+ let img = cachedCanvas . img ;
936+ img . waitingForCanvas . push ( function ( canvas ) {
937+ loadTextureFromCanvas ( canvas ) ;
938+ } ) ;
939+ } else {
940+ console . debug ( "Using cached canvas (" + canvasKey + ")" )
941+ loadTextureFromCanvas ( canvasCache [ canvasKey ] ) ;
942+ }
943+ } else {
944+ let img = new Image ( ) ;
945+ img . onerror = function ( err ) {
946+ console . warn ( err ) ;
947+ resolve ( null ) ;
948+ } ;
949+ img . waitingForCanvas = [ ] ;
950+ img . onload = function ( ) {
951+ let canvasData = processImgToCanvasData ( img ) ;
952+ loadTextureFromCanvas ( canvasData ) ;
953+
954+ for ( let c = 0 ; c < img . waitingForCanvas . length ; c ++ ) {
955+ img . waitingForCanvas [ c ] ( canvasData ) ;
956+ }
957+ } ;
958+ console . debug ( "Pre-caching canvas (" + canvasKey + ")" ) ;
959+ canvasCache [ canvasKey ] = {
960+ img : img
961+ } ;
962+ img . src = textures [ textureRef ] ;
963+ }
908964 } ) ) ;
909965 }
910966 Promise . all ( promises ) . then ( materials => materialsLoaded ( materials ) )
@@ -946,6 +1002,7 @@ ModelRender.cache = {
9461002 instanceCount : modelInstances ,
9471003
9481004 texture : textureCache ,
1005+ canvas : canvasCache ,
9491006 material : materialCache ,
9501007 geometry : geometryCache ,
9511008 instances : instanceCache ,
0 commit comments