diff --git a/packages/mesh-extras/src/SimpleRope.js b/packages/mesh-extras/src/SimpleRope.js index 66df525..ad371c5 100644 --- a/packages/mesh-extras/src/SimpleRope.js +++ b/packages/mesh-extras/src/SimpleRope.js @@ -1,4 +1,5 @@ import { Mesh, MeshMaterial } from '@pixi/mesh'; +import { WRAP_MODES } from '@pixi/constants'; import { RopeGeometry } from './geometry/RopeGeometry'; /** @@ -21,12 +22,20 @@ /** * @param {PIXI.Texture} texture - The texture to use on the rope. * @param {PIXI.Point[]} points - An array of {@link PIXI.Point} objects to construct this rope. + * @param {number} [textureScale=0] - Optional. Positive values scale rope texture + * keeping its aspect ratio. You can reduce alpha channel artifacts by providing a larger texture + * and downsampling here. If set to zero, texture will be streched instead. */ - constructor(texture, points) + constructor(texture, points, textureScale = 0) { - const ropeGeometry = new RopeGeometry(texture.height, points); + const ropeGeometry = new RopeGeometry(texture.height, points, textureScale); const meshMaterial = new MeshMaterial(texture); + if (textureScale > 0) + { + // attempt to set UV wrapping, will fail on non-power of two textures + texture.baseTexture.wrapMode = WRAP_MODES.REPEAT; + } super(ropeGeometry, meshMaterial); /** diff --git a/packages/mesh-extras/src/SimpleRope.js b/packages/mesh-extras/src/SimpleRope.js index 66df525..ad371c5 100644 --- a/packages/mesh-extras/src/SimpleRope.js +++ b/packages/mesh-extras/src/SimpleRope.js @@ -1,4 +1,5 @@ import { Mesh, MeshMaterial } from '@pixi/mesh'; +import { WRAP_MODES } from '@pixi/constants'; import { RopeGeometry } from './geometry/RopeGeometry'; /** @@ -21,12 +22,20 @@ /** * @param {PIXI.Texture} texture - The texture to use on the rope. * @param {PIXI.Point[]} points - An array of {@link PIXI.Point} objects to construct this rope. + * @param {number} [textureScale=0] - Optional. Positive values scale rope texture + * keeping its aspect ratio. You can reduce alpha channel artifacts by providing a larger texture + * and downsampling here. If set to zero, texture will be streched instead. */ - constructor(texture, points) + constructor(texture, points, textureScale = 0) { - const ropeGeometry = new RopeGeometry(texture.height, points); + const ropeGeometry = new RopeGeometry(texture.height, points, textureScale); const meshMaterial = new MeshMaterial(texture); + if (textureScale > 0) + { + // attempt to set UV wrapping, will fail on non-power of two textures + texture.baseTexture.wrapMode = WRAP_MODES.REPEAT; + } super(ropeGeometry, meshMaterial); /** diff --git a/packages/mesh-extras/src/geometry/RopeGeometry.js b/packages/mesh-extras/src/geometry/RopeGeometry.js index c16297d..0b23ad9 100644 --- a/packages/mesh-extras/src/geometry/RopeGeometry.js +++ b/packages/mesh-extras/src/geometry/RopeGeometry.js @@ -19,8 +19,15 @@ /** * @param {number} [width=200] - The width (i.e., thickness) of the rope. * @param {PIXI.Point[]} [points] - An array of {@link PIXI.Point} objects to construct this rope. + * @param {number} [textureScale=0] - By default the rope texture will be stretched to match + * rope length. If textureScale is positive this value will be treated as a scaling + * factor and the texture will preserve its aspect ratio instead. To create a tiling rope + * set baseTexture.wrapMode to {@link PIXI.WRAP_MODES.REPEAT} and use a power of two texture, + * then set textureScale=1 to keep the original texture pixel size. + * In order to reduce alpha channel artifacts provide a larger texture and downsample - + * i.e. set textureScale=0.5 to scale it down twice. */ - constructor(width = 200, points) + constructor(width = 200, points, textureScale = 0) { super(new Float32Array(points.length * 4), new Float32Array(points.length * 4), @@ -39,6 +46,13 @@ */ this.width = width; + /** + * Rope texture scale, if zero then the rope texture is stretched. + * @member {number} + * @readOnly + */ + this.textureScale = textureScale; + this.build(); } /** @@ -77,16 +91,31 @@ uvs[2] = 0; uvs[3] = 1; - // indices[0] = 0; - // indices[1] = 1; - + let amount = 0; + let prev = points[0]; + const textureWidth = this.width * this.textureScale; const total = points.length; // - 1; for (let i = 0; i < total; i++) { // time to do some smart drawing! const index = i * 4; - const amount = i / (total - 1); + + if (this.textureScale > 0) + { + // calculate pixel distance from previous point + const dx = prev.x - points[i].x; + const dy = prev.y - points[i].y; + const distance = Math.sqrt((dx * dx) + (dy * dy)); + + prev = points[i]; + amount += distance / textureWidth; + } + else + { + // stretch texture + amount = i / (total - 1); + } uvs[index] = amount; uvs[index + 1] = 0; @@ -134,8 +163,6 @@ let perpX = 0; let perpY = 0; - // this.count -= 0.2; - const vertices = this.buffers[0].data; const total = points.length; @@ -164,7 +191,7 @@ } const perpLength = Math.sqrt((perpX * perpX) + (perpY * perpY)); - const num = this.width / 2; // (20 + Math.abs(Math.sin((i + this.count) * 0.3) * 50) )* ratio; + const num = this.textureScale > 0 ? this.textureScale * this.width / 2 : this.width / 2; perpX /= perpLength; perpY /= perpLength; @@ -185,6 +212,13 @@ update() { - this.updateVertices(); + if (this.textureScale > 0) + { + this.build(); // we need to update UVs + } + else + { + this.updateVertices(); + } } }