Skip to content

Commit 010d971

Browse files
Merge pull request #32 from InventivetalentDev/image-cache
Image cache
2 parents 36c5c1f + 23f3ee8 commit 010d971

2 files changed

Lines changed: 72 additions & 15 deletions

File tree

src/model/index.js

Lines changed: 70 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ const loadedTextureCache = {};
4343
const modelInstances = {};
4444

4545
const textureCache = {};
46+
const canvasCache = {};
4647
const materialCache = {};
4748
const geometryCache = {};
4849
const 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,

test/structure.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727

2828
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>
2929
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/96/three.min.js" ></script>
30-
<script src="https://cdn.jsdelivr.net/gh/InventivetalentDev/MineRender@1.1.1/dist/model.js"></script>
30+
<script src="../dist/model.js"></script>
3131
<script>
3232
(function () {
3333

@@ -76,7 +76,7 @@
7676

7777
let modelConverter = new ModelConverter();
7878
modelConverter.structureToModels({
79-
url:"https://assets.mcasset.cloud/1.13/data/minecraft/structures/end_city/ship.nbt"
79+
url:"https://assets.mcasset.cloud/1.15.2/data/minecraft/structures/pillager_outpost/watchtower.nbt"
8080
},function (models) {
8181
console.log(models)
8282
modelRender.render(models,function () {

0 commit comments

Comments
 (0)