Skip to content

Commit 895467d

Browse files
committed
Add a hard reset of MIPs and simplify logic
1 parent 40b9683 commit 895467d

File tree

2 files changed

+52
-65
lines changed

2 files changed

+52
-65
lines changed

src/SVGMIP.js

Lines changed: 11 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -15,46 +15,29 @@ class SVGMIP {
1515
this._scale = scale;
1616
this._texture = null;
1717
this._callback = callback;
18-
this.dirty = false;
1918

2019
this.draw();
2120
}
2221

2322
draw () {
24-
if (this._texture) {
25-
this._svgRenderer._draw(this._scale, () => {
26-
const gl = this._renderer.gl;
27-
const textureData = this._getTextureData();
28-
29-
gl.bindTexture(gl.TEXTURE_2D, this._texture);
30-
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, textureData);
31-
this._callback(textureData);
32-
});
33-
} else {
34-
this._svgRenderer._draw(this._scale, () => {
35-
const textureData = this._getTextureData();
36-
const textureOptions = {
37-
auto: false,
38-
wrap: this._renderer.gl.CLAMP_TO_EDGE,
39-
src: textureData
40-
};
41-
42-
this._texture = twgl.createTexture(this._renderer.gl, textureOptions);
43-
this._callback(textureData);
44-
});
45-
}
23+
this._svgRenderer._draw(this._scale, () => {
24+
const textureData = this._getTextureData();
25+
const textureOptions = {
26+
auto: false,
27+
wrap: this._renderer.gl.CLAMP_TO_EDGE,
28+
src: textureData
29+
};
30+
31+
this._texture = twgl.createTexture(this._renderer.gl, textureOptions);
32+
this._callback(textureData);
33+
});
4634
}
4735

4836
dispose () {
4937
this._renderer.gl.deleteTexture(this.getTexture());
5038
}
5139

5240
getTexture () {
53-
if (this.dirty) {
54-
this.draw();
55-
this.dirty = false;
56-
}
57-
5841
return this._texture;
5942
}
6043

src/SVGSkin.js

Lines changed: 41 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,11 @@ class SVGSkin extends Skin {
3535
/** @type {Array.<SVGMIPs>} */
3636
this._scaledMIPs = [];
3737

38-
/** @type {Number} */
38+
/**
39+
* Ratio of the size of the SVG and the max size of the WebGL texture
40+
* @type {Number}
41+
*/
3942
this._maxTextureScale = 1;
40-
41-
/** @type {Number} */
42-
this._largestTextureScale = 1;
4343
}
4444

4545
/**
@@ -54,7 +54,6 @@ class SVGSkin extends Skin {
5454
}
5555
this._texture = null;
5656
this._scaledMIPs.length = 0;
57-
this._largestTextureScale = 1;
5857
}
5958
super.dispose();
6059
}
@@ -80,26 +79,22 @@ class SVGSkin extends Skin {
8079
* Create a MIP for a given scale and pass it a callback for updating
8180
* state when switching between scales and MIPs.
8281
* @param {number} scale - The relative size of the MIP
82+
* @param {function} resetCallback - this is a callback for doing a hard reset
83+
* of MIPs and a reset of the rotation center. Only passed in if the MIP scale is 1.
8384
* @return {SVGMIP} An object that handles creating and updating SVG textures.
8485
*/
85-
createMIP (scale) {
86-
const callback = textureData => {
87-
if (scale > this._largestTextureScale) {
88-
this._largestTextureScale = scale;
86+
createMIP (scale, resetCallback) {
87+
const textureCallback = textureData => {
88+
// Check if we have the largest MIP
89+
// eslint-disable-next-line no-use-before-define
90+
if (this._scaledMIPs[this._scaledMIPs.length - 1] === mip) {
8991
// Currently silhouette only gets scaled up
9092
this._silhouette.update(textureData);
9193
}
9294

93-
if (scale === 1) {
94-
const maxDimension = Math.max(textureData.width, textureData.height);
95-
let testScale = 2;
96-
for (testScale; maxDimension * testScale <= MAX_TEXTURE_DIMENSION; testScale *= 2) {
97-
this._maxTextureScale = testScale;
98-
}
99-
this._silhouette.update(textureData);
100-
}
95+
if (resetCallback) resetCallback();
10196
};
102-
const mip = new SVGMIP(this._renderer, this._svgRenderer, scale, callback);
97+
const mip = new SVGMIP(this._renderer, this._svgRenderer, scale, textureCallback);
10398

10499
return mip;
105100
}
@@ -108,7 +103,6 @@ class SVGSkin extends Skin {
108103
* @param {Array<number>} scale - The scaling factors to be used, each in the [0,100] range.
109104
* @return {WebGLTexture} The GL texture representation of this skin when drawing at the given scale.
110105
*/
111-
// eslint-disable-next-line no-unused-vars
112106
getTexture (scale) {
113107
// The texture only ever gets uniform scale. Take the larger of the two axes.
114108
const scaleMax = scale ? Math.max(Math.abs(scale[0]), Math.abs(scale[1])) : 100;
@@ -136,34 +130,44 @@ class SVGSkin extends Skin {
136130
}
137131

138132
/**
139-
* Set the contents of this skin to a snapshot of the provided SVG data.
140-
* @param {string} svgData - new SVG to use.
133+
* Do a hard reset of the existing MIPs by calling dispose(), setting a new
134+
* scale 1 MIP in this._scaledMIPs, and finally updating the rotationCenter.
135+
* @param {SVGMIPs} mip - An object that handles creating and updating SVG textures.
141136
* @param {Array<number>} [rotationCenter] - Optional rotation center for the SVG. If not supplied, it will be
142137
* calculated from the bounding box
143-
* @fires Skin.event:WasAltered
138+
* @fires Skin.event:WasAltered
144139
*/
145-
setSVG (svgData, rotationCenter) {
146-
this._svgRenderer.loadString(svgData);
140+
resetMIPs (mip, rotationCenter) {
141+
this._scaledMIPs.forEach(oldMIP => oldMIP.dispose());
142+
this._scaledMIPs.length = 0;
147143

148-
if (this._texture) {
149-
this._texture = this._scaledMIPs[INDEX_OFFSET];
150-
this._texture.draw();
151-
152-
for (const index in this._scaledMIPs) {
153-
if (index !== INDEX_OFFSET) {
154-
this._scaledMIPs[index].dirty = true;
155-
}
156-
}
157-
} else {
158-
const textureScale = 1;
159-
this._texture = this._scaledMIPs[INDEX_OFFSET] = this.createMIP(textureScale);
160-
}
144+
// Set new scale 1 MIP after outdated MIPs have been disposed
145+
this._texture = this._scaledMIPs[INDEX_OFFSET] = mip;
161146

162147
if (typeof rotationCenter === 'undefined') rotationCenter = this.calculateRotationCenter();
163148
this.setRotationCenter.apply(this, rotationCenter);
164149
this.emit(Skin.Events.WasAltered);
165150
}
166151

152+
/**
153+
* Set the contents of this skin to a snapshot of the provided SVG data.
154+
* @param {string} svgData - new SVG to use.
155+
* @param {Array<number>} [rotationCenter] - Optional rotation center for the SVG.
156+
*/
157+
setSVG (svgData, rotationCenter) {
158+
this._svgRenderer.loadString(svgData);
159+
160+
const maxDimension = Math.ceil(Math.max(this.size[0], this.size[1]));
161+
let testScale = 2;
162+
for (testScale; maxDimension * testScale <= MAX_TEXTURE_DIMENSION; testScale *= 2) {
163+
this._maxTextureScale = testScale;
164+
}
165+
166+
// Create the 1.0 scale MIP at INDEX_OFFSET.
167+
const textureScale = 1;
168+
const mip = this.createMIP(textureScale, () => this.resetMIPs(mip, rotationCenter));
169+
}
170+
167171
}
168172

169173
module.exports = SVGSkin;

0 commit comments

Comments
 (0)