diff --git a/src/extras/index.js b/src/extras/index.js index 267e97c..6f14e0d 100644 --- a/src/extras/index.js +++ b/src/extras/index.js @@ -11,7 +11,6 @@ module.exports = { MovieClip: require('./MovieClip'), TilingSprite: require('./TilingSprite'), - mesh: require('./mesh/index'), cacheAsBitmap: require('./cacheAsBitmap'), getChildByName: require('./getChildByName') }; diff --git a/src/extras/index.js b/src/extras/index.js index 267e97c..6f14e0d 100644 --- a/src/extras/index.js +++ b/src/extras/index.js @@ -11,7 +11,6 @@ module.exports = { MovieClip: require('./MovieClip'), TilingSprite: require('./TilingSprite'), - mesh: require('./mesh/index'), cacheAsBitmap: require('./cacheAsBitmap'), getChildByName: require('./getChildByName') }; diff --git a/src/extras/mesh/Mesh.js b/src/extras/mesh/Mesh.js deleted file mode 100644 index 30431ae..0000000 --- a/src/extras/mesh/Mesh.js +++ /dev/null @@ -1,387 +0,0 @@ -var core = require('../../core'); - -/** - * Base mesh class - * @class - * @extends Container - * @memberof PIXI.extras - * @param texture {Texture} The texture to use - * @param [vertices] {Float32Arrif you want to specify the vertices - * @param [uvs] {Float32Array} if you want to specify the uvs - * @param [indices] {Uint16Array} if you want to specify the indices - * @param [drawMode] {number} the drawMode, can be any of the Mesh.DRAW_MODES consts - */ -function Mesh(texture, vertices, uvs, indices, drawMode) -{ - core.Container.call(this); - - /** - * The texture of the Mesh - * - * @member {Texture} - */ - this.texture = texture; - - /** - * The Uvs of the Mesh - * - * @member {Float32Array} - */ - this.uvs = uvs || new Float32Array([0, 1, - 1, 1, - 1, 0, - 0, 1]); - - /** - * An array of vertices - * - * @member {Float32Array} - */ - this.vertices = vertices || new Float32Array([0, 0, - 100, 0, - 100, 100, - 0, 100]); - - /* - * @member {Uint16Array} An array containing the indices of the vertices - */ - // TODO auto generate this based on draw mode! - this.indices = indices || new Uint16Array([0, 1, 2, 3]); - - /** - * Whether the Mesh is dirty or not - * - * @member {boolean} - */ - this.dirty = true; - - /** - * The blend mode to be applied to the sprite. Set to blendModes.NORMAL to remove any blend mode. - * - * @member {number} - * @default CONST.BLEND_MODES.NORMAL; - */ - this.blendMode = core.CONST.BLEND_MODES.NORMAL; - - /** - * Triangles in canvas mode are automatically antialiased, use this value to force triangles to overlap a bit with each other. - * - * @member {number}= - */ - this.canvasPadding = 0; - - /** - * The way the Mesh should be drawn, can be any of the Mesh.DRAW_MODES consts - * - * @member {number} - */ - this.drawMode = drawMode || Mesh.DRAW_MODES.TRIANGLE_MESH; -} - -// constructor -Mesh.prototype = Object.create(core.Container.prototype); -Mesh.prototype.constructor = Mesh; -module.exports = Mesh; - -/** - * Renders the object using the WebGL renderer - * - * @param renderer {WebGLRenderer} a reference to the WebGL renderer - */ -Mesh.prototype._renderWebGL = function (renderer) -{ - renderer.setObjectRenderer(renderer.plugins.mesh); - renderer.plugins.mesh.render(this); -}; - -/** - * Renders the object using the Canvas renderer - * - * @param renderer {CanvasRenderer} - */ -Mesh.prototype._renderCanvas = function (renderer) -{ - var context = renderer.context; - - var transform = this.worldTransform; - - if (renderer.roundPixels) - { - context.setTransform(transform.a, transform.b, transform.c, transform.d, transform.tx | 0, transform.ty | 0); - } - else - { - context.setTransform(transform.a, transform.b, transform.c, transform.d, transform.tx, transform.ty); - } - - if (this.drawMode === Mesh.DRAW_MODES.TRIANGLE_MESH) - { - this._renderCanvasTriangleMesh(context); - } - else - { - this._renderCanvasTriangles(context); - } -}; - -/** - * Draws the object in Triangle Mesh mode using canvas - * - * @param context {CanvasRenderingContext2D} the current drawing context - * @private - */ -Mesh.prototype._renderCanvasTriangleMesh = function (context) -{ - // draw triangles!! - var vertices = this.vertices; - var uvs = this.uvs; - - var length = vertices.length / 2; - // this.count++; - - for (var i = 0; i < length - 2; i++) - { - // draw some triangles! - var index = i * 2; - this._renderCanvasDrawTriangle(context, vertices, uvs, index, (index + 2), (index + 4)); - } -}; - -/** - * Draws the object in triangle mode using canvas - * - * @param context {CanvasRenderingContext2D} the current drawing context - * @private - */ -Mesh.prototype._renderCanvasTriangles = function (context) -{ - // draw triangles!! - var vertices = this.vertices; - var uvs = this.uvs; - var indices = this.indices; - - var length = indices.length; - // this.count++; - - for (var i = 0; i < length; i += 3) - { - // draw some triangles! - var index0 = indices[i] * 2, index1 = indices[i + 1] * 2, index2 = indices[i + 2] * 2; - this._renderCanvasDrawTriangle(context, vertices, uvs, index0, index1, index2); - } -}; - -/** - * Draws one of the triangles that form this Mesh - * - * @param context {CanvasRenderingContext2D} the current drawing context - * @param vertices {Float32Array} a reference to the vertices of the Mesh - * @param uvs {Float32Array} a reference to the uvs of the Mesh - * @param index0 {number} the index of the first vertex - * @param index1 {number} the index of the second vertex - * @param index2 {number} the index of the third vertex - * @private - */ -Mesh.prototype._renderCanvasDrawTriangle = function (context, vertices, uvs, index0, index1, index2) -{ - var textureSource = this.texture.baseTexture.source; - var textureWidth = this.texture.width; - var textureHeight = this.texture.height; - - var x0 = vertices[index0], x1 = vertices[index1], x2 = vertices[index2]; - var y0 = vertices[index0 + 1], y1 = vertices[index1 + 1], y2 = vertices[index2 + 1]; - - var u0 = uvs[index0] * textureWidth, u1 = uvs[index1] * textureWidth, u2 = uvs[index2] * textureWidth; - var v0 = uvs[index0 + 1] * textureHeight, v1 = uvs[index1 + 1] * textureHeight, v2 = uvs[index2 + 1] * textureHeight; - - if (this.canvasPadding > 0) - { - var paddingX = this.canvasPadding / this.worldTransform.a; - var paddingY = this.canvasPadding / this.worldTransform.d; - var centerX = (x0 + x1 + x2) / 3; - var centerY = (y0 + y1 + y2) / 3; - - var normX = x0 - centerX; - var normY = y0 - centerY; - - var dist = Math.sqrt(normX * normX + normY * normY); - x0 = centerX + (normX / dist) * (dist + paddingX); - y0 = centerY + (normY / dist) * (dist + paddingY); - - // - - normX = x1 - centerX; - normY = y1 - centerY; - - dist = Math.sqrt(normX * normX + normY * normY); - x1 = centerX + (normX / dist) * (dist + paddingX); - y1 = centerY + (normY / dist) * (dist + paddingY); - - normX = x2 - centerX; - normY = y2 - centerY; - - dist = Math.sqrt(normX * normX + normY * normY); - x2 = centerX + (normX / dist) * (dist + paddingX); - y2 = centerY + (normY / dist) * (dist + paddingY); - } - - context.save(); - context.beginPath(); - - - context.moveTo(x0, y0); - context.lineTo(x1, y1); - context.lineTo(x2, y2); - - context.closePath(); - - context.clip(); - - // Compute matrix transform - var delta = (u0 * v1) + (v0 * u2) + (u1 * v2) - (v1 * u2) - (v0 * u1) - (u0 * v2); - var deltaA = (x0 * v1) + (v0 * x2) + (x1 * v2) - (v1 * x2) - (v0 * x1) - (x0 * v2); - var deltaB = (u0 * x1) + (x0 * u2) + (u1 * x2) - (x1 * u2) - (x0 * u1) - (u0 * x2); - var deltaC = (u0 * v1 * x2) + (v0 * x1 * u2) + (x0 * u1 * v2) - (x0 * v1 * u2) - (v0 * u1 * x2) - (u0 * x1 * v2); - var deltaD = (y0 * v1) + (v0 * y2) + (y1 * v2) - (v1 * y2) - (v0 * y1) - (y0 * v2); - var deltaE = (u0 * y1) + (y0 * u2) + (u1 * y2) - (y1 * u2) - (y0 * u1) - (u0 * y2); - var deltaF = (u0 * v1 * y2) + (v0 * y1 * u2) + (y0 * u1 * v2) - (y0 * v1 * u2) - (v0 * u1 * y2) - (u0 * y1 * v2); - - context.transform(deltaA / delta, deltaD / delta, - deltaB / delta, deltaE / delta, - deltaC / delta, deltaF / delta); - - context.drawImage(textureSource, 0, 0); - context.restore(); -}; - - - -/** - * Renders a flat Mesh - * - * @param Mesh {Mesh} The Mesh to render - * @private - */ -Mesh.prototype.renderMeshFlat = function (Mesh) -{ - var context = this.context; - var vertices = Mesh.vertices; - - var length = vertices.length/2; - // this.count++; - - context.beginPath(); - for (var i=1; i < length-2; i++) - { - // draw some triangles! - var index = i*2; - - var x0 = vertices[index], x1 = vertices[index+2], x2 = vertices[index+4]; - var y0 = vertices[index+1], y1 = vertices[index+3], y2 = vertices[index+5]; - - context.moveTo(x0, y0); - context.lineTo(x1, y1); - context.lineTo(x2, y2); - } - - context.fillStyle = '#FF0000'; - context.fill(); - context.closePath(); -}; - -/* -Mesh.prototype.setTexture = function (texture) -{ - //TODO SET THE TEXTURES - //TODO VISIBILITY - //TODO SETTER - - // stop current texture - this.texture = texture; - this.width = texture.frame.width; - this.height = texture.frame.height; - this.updateFrame = true; -}; - */ - -/** - * When the texture is updated, this event will fire to update the scale and frame - * - * @param event - * @private - */ - -Mesh.prototype.onTextureUpdate = function () -{ - this.updateFrame = true; -}; - -/** - * Returns the bounds of the mesh as a rectangle. The bounds calculation takes the worldTransform into account. - * - * @param matrix {Matrix} the transformation matrix of the sprite - * @return {Rectangle} the framing rectangle - */ -Mesh.prototype.getBounds = function (matrix) -{ - var worldTransform = matrix || this.worldTransform; - - var a = worldTransform.a; - var b = worldTransform.b; - var c = worldTransform.c; - var d = worldTransform.d; - var tx = worldTransform.tx; - var ty = worldTransform.ty; - - var maxX = -Infinity; - var maxY = -Infinity; - - var minX = Infinity; - var minY = Infinity; - - var vertices = this.vertices; - for (var i = 0, n = vertices.length; i < n; i += 2) - { - var rawX = vertices[i], rawY = vertices[i + 1]; - var x = (a * rawX) + (c * rawY) + tx; - var y = (d * rawY) + (b * rawX) + ty; - - minX = x < minX ? x : minX; - minY = y < minY ? y : minY; - - maxX = x > maxX ? x : maxX; - maxY = y > maxY ? y : maxY; - } - - if (minX === -Infinity || maxY === Infinity) - { - return core.math.Rectangle.EMPTY; - } - - var bounds = this._bounds; - - bounds.x = minX; - bounds.width = maxX - minX; - - bounds.y = minY; - bounds.height = maxY - minY; - - // store a reference so that if this function gets called again in the render cycle we do not have to recalculate - this._currentBounds = bounds; - - return bounds; -}; - -/** - * Different drawing buffer modes supported - * - * @static - * @constant - * @property {object} DRAW_MODES - * @property {number} DRAW_MODES.TRIANGLE_MESH - * @property {number} DRAW_MODES.TRIANGLES - */ -Mesh.DRAW_MODES = { - TRIANGLE_MESH: 0, - TRIANGLES: 1 -}; diff --git a/src/extras/index.js b/src/extras/index.js index 267e97c..6f14e0d 100644 --- a/src/extras/index.js +++ b/src/extras/index.js @@ -11,7 +11,6 @@ module.exports = { MovieClip: require('./MovieClip'), TilingSprite: require('./TilingSprite'), - mesh: require('./mesh/index'), cacheAsBitmap: require('./cacheAsBitmap'), getChildByName: require('./getChildByName') }; diff --git a/src/extras/mesh/Mesh.js b/src/extras/mesh/Mesh.js deleted file mode 100644 index 30431ae..0000000 --- a/src/extras/mesh/Mesh.js +++ /dev/null @@ -1,387 +0,0 @@ -var core = require('../../core'); - -/** - * Base mesh class - * @class - * @extends Container - * @memberof PIXI.extras - * @param texture {Texture} The texture to use - * @param [vertices] {Float32Arrif you want to specify the vertices - * @param [uvs] {Float32Array} if you want to specify the uvs - * @param [indices] {Uint16Array} if you want to specify the indices - * @param [drawMode] {number} the drawMode, can be any of the Mesh.DRAW_MODES consts - */ -function Mesh(texture, vertices, uvs, indices, drawMode) -{ - core.Container.call(this); - - /** - * The texture of the Mesh - * - * @member {Texture} - */ - this.texture = texture; - - /** - * The Uvs of the Mesh - * - * @member {Float32Array} - */ - this.uvs = uvs || new Float32Array([0, 1, - 1, 1, - 1, 0, - 0, 1]); - - /** - * An array of vertices - * - * @member {Float32Array} - */ - this.vertices = vertices || new Float32Array([0, 0, - 100, 0, - 100, 100, - 0, 100]); - - /* - * @member {Uint16Array} An array containing the indices of the vertices - */ - // TODO auto generate this based on draw mode! - this.indices = indices || new Uint16Array([0, 1, 2, 3]); - - /** - * Whether the Mesh is dirty or not - * - * @member {boolean} - */ - this.dirty = true; - - /** - * The blend mode to be applied to the sprite. Set to blendModes.NORMAL to remove any blend mode. - * - * @member {number} - * @default CONST.BLEND_MODES.NORMAL; - */ - this.blendMode = core.CONST.BLEND_MODES.NORMAL; - - /** - * Triangles in canvas mode are automatically antialiased, use this value to force triangles to overlap a bit with each other. - * - * @member {number}= - */ - this.canvasPadding = 0; - - /** - * The way the Mesh should be drawn, can be any of the Mesh.DRAW_MODES consts - * - * @member {number} - */ - this.drawMode = drawMode || Mesh.DRAW_MODES.TRIANGLE_MESH; -} - -// constructor -Mesh.prototype = Object.create(core.Container.prototype); -Mesh.prototype.constructor = Mesh; -module.exports = Mesh; - -/** - * Renders the object using the WebGL renderer - * - * @param renderer {WebGLRenderer} a reference to the WebGL renderer - */ -Mesh.prototype._renderWebGL = function (renderer) -{ - renderer.setObjectRenderer(renderer.plugins.mesh); - renderer.plugins.mesh.render(this); -}; - -/** - * Renders the object using the Canvas renderer - * - * @param renderer {CanvasRenderer} - */ -Mesh.prototype._renderCanvas = function (renderer) -{ - var context = renderer.context; - - var transform = this.worldTransform; - - if (renderer.roundPixels) - { - context.setTransform(transform.a, transform.b, transform.c, transform.d, transform.tx | 0, transform.ty | 0); - } - else - { - context.setTransform(transform.a, transform.b, transform.c, transform.d, transform.tx, transform.ty); - } - - if (this.drawMode === Mesh.DRAW_MODES.TRIANGLE_MESH) - { - this._renderCanvasTriangleMesh(context); - } - else - { - this._renderCanvasTriangles(context); - } -}; - -/** - * Draws the object in Triangle Mesh mode using canvas - * - * @param context {CanvasRenderingContext2D} the current drawing context - * @private - */ -Mesh.prototype._renderCanvasTriangleMesh = function (context) -{ - // draw triangles!! - var vertices = this.vertices; - var uvs = this.uvs; - - var length = vertices.length / 2; - // this.count++; - - for (var i = 0; i < length - 2; i++) - { - // draw some triangles! - var index = i * 2; - this._renderCanvasDrawTriangle(context, vertices, uvs, index, (index + 2), (index + 4)); - } -}; - -/** - * Draws the object in triangle mode using canvas - * - * @param context {CanvasRenderingContext2D} the current drawing context - * @private - */ -Mesh.prototype._renderCanvasTriangles = function (context) -{ - // draw triangles!! - var vertices = this.vertices; - var uvs = this.uvs; - var indices = this.indices; - - var length = indices.length; - // this.count++; - - for (var i = 0; i < length; i += 3) - { - // draw some triangles! - var index0 = indices[i] * 2, index1 = indices[i + 1] * 2, index2 = indices[i + 2] * 2; - this._renderCanvasDrawTriangle(context, vertices, uvs, index0, index1, index2); - } -}; - -/** - * Draws one of the triangles that form this Mesh - * - * @param context {CanvasRenderingContext2D} the current drawing context - * @param vertices {Float32Array} a reference to the vertices of the Mesh - * @param uvs {Float32Array} a reference to the uvs of the Mesh - * @param index0 {number} the index of the first vertex - * @param index1 {number} the index of the second vertex - * @param index2 {number} the index of the third vertex - * @private - */ -Mesh.prototype._renderCanvasDrawTriangle = function (context, vertices, uvs, index0, index1, index2) -{ - var textureSource = this.texture.baseTexture.source; - var textureWidth = this.texture.width; - var textureHeight = this.texture.height; - - var x0 = vertices[index0], x1 = vertices[index1], x2 = vertices[index2]; - var y0 = vertices[index0 + 1], y1 = vertices[index1 + 1], y2 = vertices[index2 + 1]; - - var u0 = uvs[index0] * textureWidth, u1 = uvs[index1] * textureWidth, u2 = uvs[index2] * textureWidth; - var v0 = uvs[index0 + 1] * textureHeight, v1 = uvs[index1 + 1] * textureHeight, v2 = uvs[index2 + 1] * textureHeight; - - if (this.canvasPadding > 0) - { - var paddingX = this.canvasPadding / this.worldTransform.a; - var paddingY = this.canvasPadding / this.worldTransform.d; - var centerX = (x0 + x1 + x2) / 3; - var centerY = (y0 + y1 + y2) / 3; - - var normX = x0 - centerX; - var normY = y0 - centerY; - - var dist = Math.sqrt(normX * normX + normY * normY); - x0 = centerX + (normX / dist) * (dist + paddingX); - y0 = centerY + (normY / dist) * (dist + paddingY); - - // - - normX = x1 - centerX; - normY = y1 - centerY; - - dist = Math.sqrt(normX * normX + normY * normY); - x1 = centerX + (normX / dist) * (dist + paddingX); - y1 = centerY + (normY / dist) * (dist + paddingY); - - normX = x2 - centerX; - normY = y2 - centerY; - - dist = Math.sqrt(normX * normX + normY * normY); - x2 = centerX + (normX / dist) * (dist + paddingX); - y2 = centerY + (normY / dist) * (dist + paddingY); - } - - context.save(); - context.beginPath(); - - - context.moveTo(x0, y0); - context.lineTo(x1, y1); - context.lineTo(x2, y2); - - context.closePath(); - - context.clip(); - - // Compute matrix transform - var delta = (u0 * v1) + (v0 * u2) + (u1 * v2) - (v1 * u2) - (v0 * u1) - (u0 * v2); - var deltaA = (x0 * v1) + (v0 * x2) + (x1 * v2) - (v1 * x2) - (v0 * x1) - (x0 * v2); - var deltaB = (u0 * x1) + (x0 * u2) + (u1 * x2) - (x1 * u2) - (x0 * u1) - (u0 * x2); - var deltaC = (u0 * v1 * x2) + (v0 * x1 * u2) + (x0 * u1 * v2) - (x0 * v1 * u2) - (v0 * u1 * x2) - (u0 * x1 * v2); - var deltaD = (y0 * v1) + (v0 * y2) + (y1 * v2) - (v1 * y2) - (v0 * y1) - (y0 * v2); - var deltaE = (u0 * y1) + (y0 * u2) + (u1 * y2) - (y1 * u2) - (y0 * u1) - (u0 * y2); - var deltaF = (u0 * v1 * y2) + (v0 * y1 * u2) + (y0 * u1 * v2) - (y0 * v1 * u2) - (v0 * u1 * y2) - (u0 * y1 * v2); - - context.transform(deltaA / delta, deltaD / delta, - deltaB / delta, deltaE / delta, - deltaC / delta, deltaF / delta); - - context.drawImage(textureSource, 0, 0); - context.restore(); -}; - - - -/** - * Renders a flat Mesh - * - * @param Mesh {Mesh} The Mesh to render - * @private - */ -Mesh.prototype.renderMeshFlat = function (Mesh) -{ - var context = this.context; - var vertices = Mesh.vertices; - - var length = vertices.length/2; - // this.count++; - - context.beginPath(); - for (var i=1; i < length-2; i++) - { - // draw some triangles! - var index = i*2; - - var x0 = vertices[index], x1 = vertices[index+2], x2 = vertices[index+4]; - var y0 = vertices[index+1], y1 = vertices[index+3], y2 = vertices[index+5]; - - context.moveTo(x0, y0); - context.lineTo(x1, y1); - context.lineTo(x2, y2); - } - - context.fillStyle = '#FF0000'; - context.fill(); - context.closePath(); -}; - -/* -Mesh.prototype.setTexture = function (texture) -{ - //TODO SET THE TEXTURES - //TODO VISIBILITY - //TODO SETTER - - // stop current texture - this.texture = texture; - this.width = texture.frame.width; - this.height = texture.frame.height; - this.updateFrame = true; -}; - */ - -/** - * When the texture is updated, this event will fire to update the scale and frame - * - * @param event - * @private - */ - -Mesh.prototype.onTextureUpdate = function () -{ - this.updateFrame = true; -}; - -/** - * Returns the bounds of the mesh as a rectangle. The bounds calculation takes the worldTransform into account. - * - * @param matrix {Matrix} the transformation matrix of the sprite - * @return {Rectangle} the framing rectangle - */ -Mesh.prototype.getBounds = function (matrix) -{ - var worldTransform = matrix || this.worldTransform; - - var a = worldTransform.a; - var b = worldTransform.b; - var c = worldTransform.c; - var d = worldTransform.d; - var tx = worldTransform.tx; - var ty = worldTransform.ty; - - var maxX = -Infinity; - var maxY = -Infinity; - - var minX = Infinity; - var minY = Infinity; - - var vertices = this.vertices; - for (var i = 0, n = vertices.length; i < n; i += 2) - { - var rawX = vertices[i], rawY = vertices[i + 1]; - var x = (a * rawX) + (c * rawY) + tx; - var y = (d * rawY) + (b * rawX) + ty; - - minX = x < minX ? x : minX; - minY = y < minY ? y : minY; - - maxX = x > maxX ? x : maxX; - maxY = y > maxY ? y : maxY; - } - - if (minX === -Infinity || maxY === Infinity) - { - return core.math.Rectangle.EMPTY; - } - - var bounds = this._bounds; - - bounds.x = minX; - bounds.width = maxX - minX; - - bounds.y = minY; - bounds.height = maxY - minY; - - // store a reference so that if this function gets called again in the render cycle we do not have to recalculate - this._currentBounds = bounds; - - return bounds; -}; - -/** - * Different drawing buffer modes supported - * - * @static - * @constant - * @property {object} DRAW_MODES - * @property {number} DRAW_MODES.TRIANGLE_MESH - * @property {number} DRAW_MODES.TRIANGLES - */ -Mesh.DRAW_MODES = { - TRIANGLE_MESH: 0, - TRIANGLES: 1 -}; diff --git a/src/extras/mesh/Rope.js b/src/extras/mesh/Rope.js deleted file mode 100644 index 8119995..0000000 --- a/src/extras/mesh/Rope.js +++ /dev/null @@ -1,192 +0,0 @@ -var Mesh = require('./Mesh'); - -/** - * The rope allows you to draw a texture across several points and them manipulate these points - * - *```js - * for (var i = 0; i < 20; i++) { - * points.push(new PIXI.Point(i * 50, 0)); - * }; - * var rope = new PIXI.Rope(PIXI.Texture.fromImage("snake.png"), points); - * ``` - * - * @class - * @extends Mesh - * @memberof PIXI.extras - * @param {Texture} texture - The texture to use on the rope. - * @param {Array} points - An array of {Point} objects to construct this rope. - * - */ -function Rope(texture, points) -{ - Mesh.call(this, texture); - - /* - * @member {Array} An array of points that determine the rope - */ - this.points = points; - - /* - * @member {Float32Array} An array of vertices used to construct this rope. - */ - this.vertices = new Float32Array(points.length * 4); - - /* - * @member {Float32Array} The WebGL Uvs of the rope. - */ - this.uvs = new Float32Array(points.length * 4); - - /* - * @member {Float32Array} An array containing the color components - */ - this.colors = new Float32Array(points.length * 2); - - /* - * @member {Uint16Array} An array containing the indices of the vertices - */ - this.indices = new Uint16Array(points.length * 2); - - this.refresh(); -} - - -// constructor -Rope.prototype = Object.create(Mesh.prototype); -Rope.prototype.constructor = Rope; -module.exports = Rope; - -/** - * Refreshes - * - */ -Rope.prototype.refresh = function () -{ - var points = this.points; - - if (points.length < 1) - { - return; - } - - var uvs = this.uvs; - - var indices = this.indices; - var colors = this.colors; - - // this.count -= 0.2; - - uvs[0] = 0; - uvs[1] = 0; - uvs[2] = 0; - uvs[3] = 1; - - colors[0] = 1; - colors[1] = 1; - - indices[0] = 0; - indices[1] = 1; - - var total = points.length, - point, index, amount; - - for (var i = 1; i < total; i++) - { - point = points[i]; - index = i * 4; - // time to do some smart drawing! - amount = i / (total-1); - - if (i%2) - { - uvs[index] = amount; - uvs[index+1] = 0; - - uvs[index+2] = amount; - uvs[index+3] = 1; - } - else - { - uvs[index] = amount; - uvs[index+1] = 0; - - uvs[index+2] = amount; - uvs[index+3] = 1; - } - - index = i * 2; - colors[index] = 1; - colors[index+1] = 1; - - index = i * 2; - indices[index] = index; - indices[index + 1] = index + 1; - } -}; - -/* - * Updates the object transform for rendering - * - * @private - */ -Rope.prototype.updateTransform = function () -{ - var points = this.points; - - if (points.length < 1) - { - return; - } - - var lastPoint = points[0]; - var nextPoint; - var perpX = 0; - var perpY = 0; - - // this.count -= 0.2; - - var vertices = this.vertices; - var total = points.length, - point, index, ratio, perpLength, num; - - for (var i = 0; i < total; i++) - { - point = points[i]; - index = i * 4; - - if (i < points.length-1) - { - nextPoint = points[i+1]; - } - else - { - nextPoint = point; - } - - perpY = -(nextPoint.x - lastPoint.x); - perpX = nextPoint.y - lastPoint.y; - - ratio = (1 - (i / (total-1))) * 10; - - if (ratio > 1) - { - ratio = 1; - } - - perpLength = Math.sqrt(perpX * perpX + perpY * perpY); - num = this.texture.height / 2; //(20 + Math.abs(Math.sin((i + this.count) * 0.3) * 50) )* ratio; - perpX /= perpLength; - perpY /= perpLength; - - perpX *= num; - perpY *= num; - - vertices[index] = point.x + perpX; - vertices[index+1] = point.y + perpY; - vertices[index+2] = point.x - perpX; - vertices[index+3] = point.y - perpY; - - lastPoint = point; - } - - this.containerUpdateTransform(); -}; diff --git a/src/extras/index.js b/src/extras/index.js index 267e97c..6f14e0d 100644 --- a/src/extras/index.js +++ b/src/extras/index.js @@ -11,7 +11,6 @@ module.exports = { MovieClip: require('./MovieClip'), TilingSprite: require('./TilingSprite'), - mesh: require('./mesh/index'), cacheAsBitmap: require('./cacheAsBitmap'), getChildByName: require('./getChildByName') }; diff --git a/src/extras/mesh/Mesh.js b/src/extras/mesh/Mesh.js deleted file mode 100644 index 30431ae..0000000 --- a/src/extras/mesh/Mesh.js +++ /dev/null @@ -1,387 +0,0 @@ -var core = require('../../core'); - -/** - * Base mesh class - * @class - * @extends Container - * @memberof PIXI.extras - * @param texture {Texture} The texture to use - * @param [vertices] {Float32Arrif you want to specify the vertices - * @param [uvs] {Float32Array} if you want to specify the uvs - * @param [indices] {Uint16Array} if you want to specify the indices - * @param [drawMode] {number} the drawMode, can be any of the Mesh.DRAW_MODES consts - */ -function Mesh(texture, vertices, uvs, indices, drawMode) -{ - core.Container.call(this); - - /** - * The texture of the Mesh - * - * @member {Texture} - */ - this.texture = texture; - - /** - * The Uvs of the Mesh - * - * @member {Float32Array} - */ - this.uvs = uvs || new Float32Array([0, 1, - 1, 1, - 1, 0, - 0, 1]); - - /** - * An array of vertices - * - * @member {Float32Array} - */ - this.vertices = vertices || new Float32Array([0, 0, - 100, 0, - 100, 100, - 0, 100]); - - /* - * @member {Uint16Array} An array containing the indices of the vertices - */ - // TODO auto generate this based on draw mode! - this.indices = indices || new Uint16Array([0, 1, 2, 3]); - - /** - * Whether the Mesh is dirty or not - * - * @member {boolean} - */ - this.dirty = true; - - /** - * The blend mode to be applied to the sprite. Set to blendModes.NORMAL to remove any blend mode. - * - * @member {number} - * @default CONST.BLEND_MODES.NORMAL; - */ - this.blendMode = core.CONST.BLEND_MODES.NORMAL; - - /** - * Triangles in canvas mode are automatically antialiased, use this value to force triangles to overlap a bit with each other. - * - * @member {number}= - */ - this.canvasPadding = 0; - - /** - * The way the Mesh should be drawn, can be any of the Mesh.DRAW_MODES consts - * - * @member {number} - */ - this.drawMode = drawMode || Mesh.DRAW_MODES.TRIANGLE_MESH; -} - -// constructor -Mesh.prototype = Object.create(core.Container.prototype); -Mesh.prototype.constructor = Mesh; -module.exports = Mesh; - -/** - * Renders the object using the WebGL renderer - * - * @param renderer {WebGLRenderer} a reference to the WebGL renderer - */ -Mesh.prototype._renderWebGL = function (renderer) -{ - renderer.setObjectRenderer(renderer.plugins.mesh); - renderer.plugins.mesh.render(this); -}; - -/** - * Renders the object using the Canvas renderer - * - * @param renderer {CanvasRenderer} - */ -Mesh.prototype._renderCanvas = function (renderer) -{ - var context = renderer.context; - - var transform = this.worldTransform; - - if (renderer.roundPixels) - { - context.setTransform(transform.a, transform.b, transform.c, transform.d, transform.tx | 0, transform.ty | 0); - } - else - { - context.setTransform(transform.a, transform.b, transform.c, transform.d, transform.tx, transform.ty); - } - - if (this.drawMode === Mesh.DRAW_MODES.TRIANGLE_MESH) - { - this._renderCanvasTriangleMesh(context); - } - else - { - this._renderCanvasTriangles(context); - } -}; - -/** - * Draws the object in Triangle Mesh mode using canvas - * - * @param context {CanvasRenderingContext2D} the current drawing context - * @private - */ -Mesh.prototype._renderCanvasTriangleMesh = function (context) -{ - // draw triangles!! - var vertices = this.vertices; - var uvs = this.uvs; - - var length = vertices.length / 2; - // this.count++; - - for (var i = 0; i < length - 2; i++) - { - // draw some triangles! - var index = i * 2; - this._renderCanvasDrawTriangle(context, vertices, uvs, index, (index + 2), (index + 4)); - } -}; - -/** - * Draws the object in triangle mode using canvas - * - * @param context {CanvasRenderingContext2D} the current drawing context - * @private - */ -Mesh.prototype._renderCanvasTriangles = function (context) -{ - // draw triangles!! - var vertices = this.vertices; - var uvs = this.uvs; - var indices = this.indices; - - var length = indices.length; - // this.count++; - - for (var i = 0; i < length; i += 3) - { - // draw some triangles! - var index0 = indices[i] * 2, index1 = indices[i + 1] * 2, index2 = indices[i + 2] * 2; - this._renderCanvasDrawTriangle(context, vertices, uvs, index0, index1, index2); - } -}; - -/** - * Draws one of the triangles that form this Mesh - * - * @param context {CanvasRenderingContext2D} the current drawing context - * @param vertices {Float32Array} a reference to the vertices of the Mesh - * @param uvs {Float32Array} a reference to the uvs of the Mesh - * @param index0 {number} the index of the first vertex - * @param index1 {number} the index of the second vertex - * @param index2 {number} the index of the third vertex - * @private - */ -Mesh.prototype._renderCanvasDrawTriangle = function (context, vertices, uvs, index0, index1, index2) -{ - var textureSource = this.texture.baseTexture.source; - var textureWidth = this.texture.width; - var textureHeight = this.texture.height; - - var x0 = vertices[index0], x1 = vertices[index1], x2 = vertices[index2]; - var y0 = vertices[index0 + 1], y1 = vertices[index1 + 1], y2 = vertices[index2 + 1]; - - var u0 = uvs[index0] * textureWidth, u1 = uvs[index1] * textureWidth, u2 = uvs[index2] * textureWidth; - var v0 = uvs[index0 + 1] * textureHeight, v1 = uvs[index1 + 1] * textureHeight, v2 = uvs[index2 + 1] * textureHeight; - - if (this.canvasPadding > 0) - { - var paddingX = this.canvasPadding / this.worldTransform.a; - var paddingY = this.canvasPadding / this.worldTransform.d; - var centerX = (x0 + x1 + x2) / 3; - var centerY = (y0 + y1 + y2) / 3; - - var normX = x0 - centerX; - var normY = y0 - centerY; - - var dist = Math.sqrt(normX * normX + normY * normY); - x0 = centerX + (normX / dist) * (dist + paddingX); - y0 = centerY + (normY / dist) * (dist + paddingY); - - // - - normX = x1 - centerX; - normY = y1 - centerY; - - dist = Math.sqrt(normX * normX + normY * normY); - x1 = centerX + (normX / dist) * (dist + paddingX); - y1 = centerY + (normY / dist) * (dist + paddingY); - - normX = x2 - centerX; - normY = y2 - centerY; - - dist = Math.sqrt(normX * normX + normY * normY); - x2 = centerX + (normX / dist) * (dist + paddingX); - y2 = centerY + (normY / dist) * (dist + paddingY); - } - - context.save(); - context.beginPath(); - - - context.moveTo(x0, y0); - context.lineTo(x1, y1); - context.lineTo(x2, y2); - - context.closePath(); - - context.clip(); - - // Compute matrix transform - var delta = (u0 * v1) + (v0 * u2) + (u1 * v2) - (v1 * u2) - (v0 * u1) - (u0 * v2); - var deltaA = (x0 * v1) + (v0 * x2) + (x1 * v2) - (v1 * x2) - (v0 * x1) - (x0 * v2); - var deltaB = (u0 * x1) + (x0 * u2) + (u1 * x2) - (x1 * u2) - (x0 * u1) - (u0 * x2); - var deltaC = (u0 * v1 * x2) + (v0 * x1 * u2) + (x0 * u1 * v2) - (x0 * v1 * u2) - (v0 * u1 * x2) - (u0 * x1 * v2); - var deltaD = (y0 * v1) + (v0 * y2) + (y1 * v2) - (v1 * y2) - (v0 * y1) - (y0 * v2); - var deltaE = (u0 * y1) + (y0 * u2) + (u1 * y2) - (y1 * u2) - (y0 * u1) - (u0 * y2); - var deltaF = (u0 * v1 * y2) + (v0 * y1 * u2) + (y0 * u1 * v2) - (y0 * v1 * u2) - (v0 * u1 * y2) - (u0 * y1 * v2); - - context.transform(deltaA / delta, deltaD / delta, - deltaB / delta, deltaE / delta, - deltaC / delta, deltaF / delta); - - context.drawImage(textureSource, 0, 0); - context.restore(); -}; - - - -/** - * Renders a flat Mesh - * - * @param Mesh {Mesh} The Mesh to render - * @private - */ -Mesh.prototype.renderMeshFlat = function (Mesh) -{ - var context = this.context; - var vertices = Mesh.vertices; - - var length = vertices.length/2; - // this.count++; - - context.beginPath(); - for (var i=1; i < length-2; i++) - { - // draw some triangles! - var index = i*2; - - var x0 = vertices[index], x1 = vertices[index+2], x2 = vertices[index+4]; - var y0 = vertices[index+1], y1 = vertices[index+3], y2 = vertices[index+5]; - - context.moveTo(x0, y0); - context.lineTo(x1, y1); - context.lineTo(x2, y2); - } - - context.fillStyle = '#FF0000'; - context.fill(); - context.closePath(); -}; - -/* -Mesh.prototype.setTexture = function (texture) -{ - //TODO SET THE TEXTURES - //TODO VISIBILITY - //TODO SETTER - - // stop current texture - this.texture = texture; - this.width = texture.frame.width; - this.height = texture.frame.height; - this.updateFrame = true; -}; - */ - -/** - * When the texture is updated, this event will fire to update the scale and frame - * - * @param event - * @private - */ - -Mesh.prototype.onTextureUpdate = function () -{ - this.updateFrame = true; -}; - -/** - * Returns the bounds of the mesh as a rectangle. The bounds calculation takes the worldTransform into account. - * - * @param matrix {Matrix} the transformation matrix of the sprite - * @return {Rectangle} the framing rectangle - */ -Mesh.prototype.getBounds = function (matrix) -{ - var worldTransform = matrix || this.worldTransform; - - var a = worldTransform.a; - var b = worldTransform.b; - var c = worldTransform.c; - var d = worldTransform.d; - var tx = worldTransform.tx; - var ty = worldTransform.ty; - - var maxX = -Infinity; - var maxY = -Infinity; - - var minX = Infinity; - var minY = Infinity; - - var vertices = this.vertices; - for (var i = 0, n = vertices.length; i < n; i += 2) - { - var rawX = vertices[i], rawY = vertices[i + 1]; - var x = (a * rawX) + (c * rawY) + tx; - var y = (d * rawY) + (b * rawX) + ty; - - minX = x < minX ? x : minX; - minY = y < minY ? y : minY; - - maxX = x > maxX ? x : maxX; - maxY = y > maxY ? y : maxY; - } - - if (minX === -Infinity || maxY === Infinity) - { - return core.math.Rectangle.EMPTY; - } - - var bounds = this._bounds; - - bounds.x = minX; - bounds.width = maxX - minX; - - bounds.y = minY; - bounds.height = maxY - minY; - - // store a reference so that if this function gets called again in the render cycle we do not have to recalculate - this._currentBounds = bounds; - - return bounds; -}; - -/** - * Different drawing buffer modes supported - * - * @static - * @constant - * @property {object} DRAW_MODES - * @property {number} DRAW_MODES.TRIANGLE_MESH - * @property {number} DRAW_MODES.TRIANGLES - */ -Mesh.DRAW_MODES = { - TRIANGLE_MESH: 0, - TRIANGLES: 1 -}; diff --git a/src/extras/mesh/Rope.js b/src/extras/mesh/Rope.js deleted file mode 100644 index 8119995..0000000 --- a/src/extras/mesh/Rope.js +++ /dev/null @@ -1,192 +0,0 @@ -var Mesh = require('./Mesh'); - -/** - * The rope allows you to draw a texture across several points and them manipulate these points - * - *```js - * for (var i = 0; i < 20; i++) { - * points.push(new PIXI.Point(i * 50, 0)); - * }; - * var rope = new PIXI.Rope(PIXI.Texture.fromImage("snake.png"), points); - * ``` - * - * @class - * @extends Mesh - * @memberof PIXI.extras - * @param {Texture} texture - The texture to use on the rope. - * @param {Array} points - An array of {Point} objects to construct this rope. - * - */ -function Rope(texture, points) -{ - Mesh.call(this, texture); - - /* - * @member {Array} An array of points that determine the rope - */ - this.points = points; - - /* - * @member {Float32Array} An array of vertices used to construct this rope. - */ - this.vertices = new Float32Array(points.length * 4); - - /* - * @member {Float32Array} The WebGL Uvs of the rope. - */ - this.uvs = new Float32Array(points.length * 4); - - /* - * @member {Float32Array} An array containing the color components - */ - this.colors = new Float32Array(points.length * 2); - - /* - * @member {Uint16Array} An array containing the indices of the vertices - */ - this.indices = new Uint16Array(points.length * 2); - - this.refresh(); -} - - -// constructor -Rope.prototype = Object.create(Mesh.prototype); -Rope.prototype.constructor = Rope; -module.exports = Rope; - -/** - * Refreshes - * - */ -Rope.prototype.refresh = function () -{ - var points = this.points; - - if (points.length < 1) - { - return; - } - - var uvs = this.uvs; - - var indices = this.indices; - var colors = this.colors; - - // this.count -= 0.2; - - uvs[0] = 0; - uvs[1] = 0; - uvs[2] = 0; - uvs[3] = 1; - - colors[0] = 1; - colors[1] = 1; - - indices[0] = 0; - indices[1] = 1; - - var total = points.length, - point, index, amount; - - for (var i = 1; i < total; i++) - { - point = points[i]; - index = i * 4; - // time to do some smart drawing! - amount = i / (total-1); - - if (i%2) - { - uvs[index] = amount; - uvs[index+1] = 0; - - uvs[index+2] = amount; - uvs[index+3] = 1; - } - else - { - uvs[index] = amount; - uvs[index+1] = 0; - - uvs[index+2] = amount; - uvs[index+3] = 1; - } - - index = i * 2; - colors[index] = 1; - colors[index+1] = 1; - - index = i * 2; - indices[index] = index; - indices[index + 1] = index + 1; - } -}; - -/* - * Updates the object transform for rendering - * - * @private - */ -Rope.prototype.updateTransform = function () -{ - var points = this.points; - - if (points.length < 1) - { - return; - } - - var lastPoint = points[0]; - var nextPoint; - var perpX = 0; - var perpY = 0; - - // this.count -= 0.2; - - var vertices = this.vertices; - var total = points.length, - point, index, ratio, perpLength, num; - - for (var i = 0; i < total; i++) - { - point = points[i]; - index = i * 4; - - if (i < points.length-1) - { - nextPoint = points[i+1]; - } - else - { - nextPoint = point; - } - - perpY = -(nextPoint.x - lastPoint.x); - perpX = nextPoint.y - lastPoint.y; - - ratio = (1 - (i / (total-1))) * 10; - - if (ratio > 1) - { - ratio = 1; - } - - perpLength = Math.sqrt(perpX * perpX + perpY * perpY); - num = this.texture.height / 2; //(20 + Math.abs(Math.sin((i + this.count) * 0.3) * 50) )* ratio; - perpX /= perpLength; - perpY /= perpLength; - - perpX *= num; - perpY *= num; - - vertices[index] = point.x + perpX; - vertices[index+1] = point.y + perpY; - vertices[index+2] = point.x - perpX; - vertices[index+3] = point.y - perpY; - - lastPoint = point; - } - - this.containerUpdateTransform(); -}; diff --git a/src/extras/mesh/index.js b/src/extras/mesh/index.js deleted file mode 100644 index dd37f87..0000000 --- a/src/extras/mesh/index.js +++ /dev/null @@ -1,16 +0,0 @@ -/** - * @file Main export of the PIXI extras library - * @author Mat Groves - * @copyright 2013-2015 GoodBoyDigital - * @license {@link https://github.com/GoodBoyDigital/pixi.js/blob/master/LICENSE|MIT License} - */ - -/** - * @namespace PIXI.extras - */ -module.exports = { - Mesh: require('./Mesh'), - Rope: require('./Rope'), - MeshRenderer: require('./webgl/MeshRenderer'), - MeshShader: require('./webgl/MeshShader') -}; diff --git a/src/extras/index.js b/src/extras/index.js index 267e97c..6f14e0d 100644 --- a/src/extras/index.js +++ b/src/extras/index.js @@ -11,7 +11,6 @@ module.exports = { MovieClip: require('./MovieClip'), TilingSprite: require('./TilingSprite'), - mesh: require('./mesh/index'), cacheAsBitmap: require('./cacheAsBitmap'), getChildByName: require('./getChildByName') }; diff --git a/src/extras/mesh/Mesh.js b/src/extras/mesh/Mesh.js deleted file mode 100644 index 30431ae..0000000 --- a/src/extras/mesh/Mesh.js +++ /dev/null @@ -1,387 +0,0 @@ -var core = require('../../core'); - -/** - * Base mesh class - * @class - * @extends Container - * @memberof PIXI.extras - * @param texture {Texture} The texture to use - * @param [vertices] {Float32Arrif you want to specify the vertices - * @param [uvs] {Float32Array} if you want to specify the uvs - * @param [indices] {Uint16Array} if you want to specify the indices - * @param [drawMode] {number} the drawMode, can be any of the Mesh.DRAW_MODES consts - */ -function Mesh(texture, vertices, uvs, indices, drawMode) -{ - core.Container.call(this); - - /** - * The texture of the Mesh - * - * @member {Texture} - */ - this.texture = texture; - - /** - * The Uvs of the Mesh - * - * @member {Float32Array} - */ - this.uvs = uvs || new Float32Array([0, 1, - 1, 1, - 1, 0, - 0, 1]); - - /** - * An array of vertices - * - * @member {Float32Array} - */ - this.vertices = vertices || new Float32Array([0, 0, - 100, 0, - 100, 100, - 0, 100]); - - /* - * @member {Uint16Array} An array containing the indices of the vertices - */ - // TODO auto generate this based on draw mode! - this.indices = indices || new Uint16Array([0, 1, 2, 3]); - - /** - * Whether the Mesh is dirty or not - * - * @member {boolean} - */ - this.dirty = true; - - /** - * The blend mode to be applied to the sprite. Set to blendModes.NORMAL to remove any blend mode. - * - * @member {number} - * @default CONST.BLEND_MODES.NORMAL; - */ - this.blendMode = core.CONST.BLEND_MODES.NORMAL; - - /** - * Triangles in canvas mode are automatically antialiased, use this value to force triangles to overlap a bit with each other. - * - * @member {number}= - */ - this.canvasPadding = 0; - - /** - * The way the Mesh should be drawn, can be any of the Mesh.DRAW_MODES consts - * - * @member {number} - */ - this.drawMode = drawMode || Mesh.DRAW_MODES.TRIANGLE_MESH; -} - -// constructor -Mesh.prototype = Object.create(core.Container.prototype); -Mesh.prototype.constructor = Mesh; -module.exports = Mesh; - -/** - * Renders the object using the WebGL renderer - * - * @param renderer {WebGLRenderer} a reference to the WebGL renderer - */ -Mesh.prototype._renderWebGL = function (renderer) -{ - renderer.setObjectRenderer(renderer.plugins.mesh); - renderer.plugins.mesh.render(this); -}; - -/** - * Renders the object using the Canvas renderer - * - * @param renderer {CanvasRenderer} - */ -Mesh.prototype._renderCanvas = function (renderer) -{ - var context = renderer.context; - - var transform = this.worldTransform; - - if (renderer.roundPixels) - { - context.setTransform(transform.a, transform.b, transform.c, transform.d, transform.tx | 0, transform.ty | 0); - } - else - { - context.setTransform(transform.a, transform.b, transform.c, transform.d, transform.tx, transform.ty); - } - - if (this.drawMode === Mesh.DRAW_MODES.TRIANGLE_MESH) - { - this._renderCanvasTriangleMesh(context); - } - else - { - this._renderCanvasTriangles(context); - } -}; - -/** - * Draws the object in Triangle Mesh mode using canvas - * - * @param context {CanvasRenderingContext2D} the current drawing context - * @private - */ -Mesh.prototype._renderCanvasTriangleMesh = function (context) -{ - // draw triangles!! - var vertices = this.vertices; - var uvs = this.uvs; - - var length = vertices.length / 2; - // this.count++; - - for (var i = 0; i < length - 2; i++) - { - // draw some triangles! - var index = i * 2; - this._renderCanvasDrawTriangle(context, vertices, uvs, index, (index + 2), (index + 4)); - } -}; - -/** - * Draws the object in triangle mode using canvas - * - * @param context {CanvasRenderingContext2D} the current drawing context - * @private - */ -Mesh.prototype._renderCanvasTriangles = function (context) -{ - // draw triangles!! - var vertices = this.vertices; - var uvs = this.uvs; - var indices = this.indices; - - var length = indices.length; - // this.count++; - - for (var i = 0; i < length; i += 3) - { - // draw some triangles! - var index0 = indices[i] * 2, index1 = indices[i + 1] * 2, index2 = indices[i + 2] * 2; - this._renderCanvasDrawTriangle(context, vertices, uvs, index0, index1, index2); - } -}; - -/** - * Draws one of the triangles that form this Mesh - * - * @param context {CanvasRenderingContext2D} the current drawing context - * @param vertices {Float32Array} a reference to the vertices of the Mesh - * @param uvs {Float32Array} a reference to the uvs of the Mesh - * @param index0 {number} the index of the first vertex - * @param index1 {number} the index of the second vertex - * @param index2 {number} the index of the third vertex - * @private - */ -Mesh.prototype._renderCanvasDrawTriangle = function (context, vertices, uvs, index0, index1, index2) -{ - var textureSource = this.texture.baseTexture.source; - var textureWidth = this.texture.width; - var textureHeight = this.texture.height; - - var x0 = vertices[index0], x1 = vertices[index1], x2 = vertices[index2]; - var y0 = vertices[index0 + 1], y1 = vertices[index1 + 1], y2 = vertices[index2 + 1]; - - var u0 = uvs[index0] * textureWidth, u1 = uvs[index1] * textureWidth, u2 = uvs[index2] * textureWidth; - var v0 = uvs[index0 + 1] * textureHeight, v1 = uvs[index1 + 1] * textureHeight, v2 = uvs[index2 + 1] * textureHeight; - - if (this.canvasPadding > 0) - { - var paddingX = this.canvasPadding / this.worldTransform.a; - var paddingY = this.canvasPadding / this.worldTransform.d; - var centerX = (x0 + x1 + x2) / 3; - var centerY = (y0 + y1 + y2) / 3; - - var normX = x0 - centerX; - var normY = y0 - centerY; - - var dist = Math.sqrt(normX * normX + normY * normY); - x0 = centerX + (normX / dist) * (dist + paddingX); - y0 = centerY + (normY / dist) * (dist + paddingY); - - // - - normX = x1 - centerX; - normY = y1 - centerY; - - dist = Math.sqrt(normX * normX + normY * normY); - x1 = centerX + (normX / dist) * (dist + paddingX); - y1 = centerY + (normY / dist) * (dist + paddingY); - - normX = x2 - centerX; - normY = y2 - centerY; - - dist = Math.sqrt(normX * normX + normY * normY); - x2 = centerX + (normX / dist) * (dist + paddingX); - y2 = centerY + (normY / dist) * (dist + paddingY); - } - - context.save(); - context.beginPath(); - - - context.moveTo(x0, y0); - context.lineTo(x1, y1); - context.lineTo(x2, y2); - - context.closePath(); - - context.clip(); - - // Compute matrix transform - var delta = (u0 * v1) + (v0 * u2) + (u1 * v2) - (v1 * u2) - (v0 * u1) - (u0 * v2); - var deltaA = (x0 * v1) + (v0 * x2) + (x1 * v2) - (v1 * x2) - (v0 * x1) - (x0 * v2); - var deltaB = (u0 * x1) + (x0 * u2) + (u1 * x2) - (x1 * u2) - (x0 * u1) - (u0 * x2); - var deltaC = (u0 * v1 * x2) + (v0 * x1 * u2) + (x0 * u1 * v2) - (x0 * v1 * u2) - (v0 * u1 * x2) - (u0 * x1 * v2); - var deltaD = (y0 * v1) + (v0 * y2) + (y1 * v2) - (v1 * y2) - (v0 * y1) - (y0 * v2); - var deltaE = (u0 * y1) + (y0 * u2) + (u1 * y2) - (y1 * u2) - (y0 * u1) - (u0 * y2); - var deltaF = (u0 * v1 * y2) + (v0 * y1 * u2) + (y0 * u1 * v2) - (y0 * v1 * u2) - (v0 * u1 * y2) - (u0 * y1 * v2); - - context.transform(deltaA / delta, deltaD / delta, - deltaB / delta, deltaE / delta, - deltaC / delta, deltaF / delta); - - context.drawImage(textureSource, 0, 0); - context.restore(); -}; - - - -/** - * Renders a flat Mesh - * - * @param Mesh {Mesh} The Mesh to render - * @private - */ -Mesh.prototype.renderMeshFlat = function (Mesh) -{ - var context = this.context; - var vertices = Mesh.vertices; - - var length = vertices.length/2; - // this.count++; - - context.beginPath(); - for (var i=1; i < length-2; i++) - { - // draw some triangles! - var index = i*2; - - var x0 = vertices[index], x1 = vertices[index+2], x2 = vertices[index+4]; - var y0 = vertices[index+1], y1 = vertices[index+3], y2 = vertices[index+5]; - - context.moveTo(x0, y0); - context.lineTo(x1, y1); - context.lineTo(x2, y2); - } - - context.fillStyle = '#FF0000'; - context.fill(); - context.closePath(); -}; - -/* -Mesh.prototype.setTexture = function (texture) -{ - //TODO SET THE TEXTURES - //TODO VISIBILITY - //TODO SETTER - - // stop current texture - this.texture = texture; - this.width = texture.frame.width; - this.height = texture.frame.height; - this.updateFrame = true; -}; - */ - -/** - * When the texture is updated, this event will fire to update the scale and frame - * - * @param event - * @private - */ - -Mesh.prototype.onTextureUpdate = function () -{ - this.updateFrame = true; -}; - -/** - * Returns the bounds of the mesh as a rectangle. The bounds calculation takes the worldTransform into account. - * - * @param matrix {Matrix} the transformation matrix of the sprite - * @return {Rectangle} the framing rectangle - */ -Mesh.prototype.getBounds = function (matrix) -{ - var worldTransform = matrix || this.worldTransform; - - var a = worldTransform.a; - var b = worldTransform.b; - var c = worldTransform.c; - var d = worldTransform.d; - var tx = worldTransform.tx; - var ty = worldTransform.ty; - - var maxX = -Infinity; - var maxY = -Infinity; - - var minX = Infinity; - var minY = Infinity; - - var vertices = this.vertices; - for (var i = 0, n = vertices.length; i < n; i += 2) - { - var rawX = vertices[i], rawY = vertices[i + 1]; - var x = (a * rawX) + (c * rawY) + tx; - var y = (d * rawY) + (b * rawX) + ty; - - minX = x < minX ? x : minX; - minY = y < minY ? y : minY; - - maxX = x > maxX ? x : maxX; - maxY = y > maxY ? y : maxY; - } - - if (minX === -Infinity || maxY === Infinity) - { - return core.math.Rectangle.EMPTY; - } - - var bounds = this._bounds; - - bounds.x = minX; - bounds.width = maxX - minX; - - bounds.y = minY; - bounds.height = maxY - minY; - - // store a reference so that if this function gets called again in the render cycle we do not have to recalculate - this._currentBounds = bounds; - - return bounds; -}; - -/** - * Different drawing buffer modes supported - * - * @static - * @constant - * @property {object} DRAW_MODES - * @property {number} DRAW_MODES.TRIANGLE_MESH - * @property {number} DRAW_MODES.TRIANGLES - */ -Mesh.DRAW_MODES = { - TRIANGLE_MESH: 0, - TRIANGLES: 1 -}; diff --git a/src/extras/mesh/Rope.js b/src/extras/mesh/Rope.js deleted file mode 100644 index 8119995..0000000 --- a/src/extras/mesh/Rope.js +++ /dev/null @@ -1,192 +0,0 @@ -var Mesh = require('./Mesh'); - -/** - * The rope allows you to draw a texture across several points and them manipulate these points - * - *```js - * for (var i = 0; i < 20; i++) { - * points.push(new PIXI.Point(i * 50, 0)); - * }; - * var rope = new PIXI.Rope(PIXI.Texture.fromImage("snake.png"), points); - * ``` - * - * @class - * @extends Mesh - * @memberof PIXI.extras - * @param {Texture} texture - The texture to use on the rope. - * @param {Array} points - An array of {Point} objects to construct this rope. - * - */ -function Rope(texture, points) -{ - Mesh.call(this, texture); - - /* - * @member {Array} An array of points that determine the rope - */ - this.points = points; - - /* - * @member {Float32Array} An array of vertices used to construct this rope. - */ - this.vertices = new Float32Array(points.length * 4); - - /* - * @member {Float32Array} The WebGL Uvs of the rope. - */ - this.uvs = new Float32Array(points.length * 4); - - /* - * @member {Float32Array} An array containing the color components - */ - this.colors = new Float32Array(points.length * 2); - - /* - * @member {Uint16Array} An array containing the indices of the vertices - */ - this.indices = new Uint16Array(points.length * 2); - - this.refresh(); -} - - -// constructor -Rope.prototype = Object.create(Mesh.prototype); -Rope.prototype.constructor = Rope; -module.exports = Rope; - -/** - * Refreshes - * - */ -Rope.prototype.refresh = function () -{ - var points = this.points; - - if (points.length < 1) - { - return; - } - - var uvs = this.uvs; - - var indices = this.indices; - var colors = this.colors; - - // this.count -= 0.2; - - uvs[0] = 0; - uvs[1] = 0; - uvs[2] = 0; - uvs[3] = 1; - - colors[0] = 1; - colors[1] = 1; - - indices[0] = 0; - indices[1] = 1; - - var total = points.length, - point, index, amount; - - for (var i = 1; i < total; i++) - { - point = points[i]; - index = i * 4; - // time to do some smart drawing! - amount = i / (total-1); - - if (i%2) - { - uvs[index] = amount; - uvs[index+1] = 0; - - uvs[index+2] = amount; - uvs[index+3] = 1; - } - else - { - uvs[index] = amount; - uvs[index+1] = 0; - - uvs[index+2] = amount; - uvs[index+3] = 1; - } - - index = i * 2; - colors[index] = 1; - colors[index+1] = 1; - - index = i * 2; - indices[index] = index; - indices[index + 1] = index + 1; - } -}; - -/* - * Updates the object transform for rendering - * - * @private - */ -Rope.prototype.updateTransform = function () -{ - var points = this.points; - - if (points.length < 1) - { - return; - } - - var lastPoint = points[0]; - var nextPoint; - var perpX = 0; - var perpY = 0; - - // this.count -= 0.2; - - var vertices = this.vertices; - var total = points.length, - point, index, ratio, perpLength, num; - - for (var i = 0; i < total; i++) - { - point = points[i]; - index = i * 4; - - if (i < points.length-1) - { - nextPoint = points[i+1]; - } - else - { - nextPoint = point; - } - - perpY = -(nextPoint.x - lastPoint.x); - perpX = nextPoint.y - lastPoint.y; - - ratio = (1 - (i / (total-1))) * 10; - - if (ratio > 1) - { - ratio = 1; - } - - perpLength = Math.sqrt(perpX * perpX + perpY * perpY); - num = this.texture.height / 2; //(20 + Math.abs(Math.sin((i + this.count) * 0.3) * 50) )* ratio; - perpX /= perpLength; - perpY /= perpLength; - - perpX *= num; - perpY *= num; - - vertices[index] = point.x + perpX; - vertices[index+1] = point.y + perpY; - vertices[index+2] = point.x - perpX; - vertices[index+3] = point.y - perpY; - - lastPoint = point; - } - - this.containerUpdateTransform(); -}; diff --git a/src/extras/mesh/index.js b/src/extras/mesh/index.js deleted file mode 100644 index dd37f87..0000000 --- a/src/extras/mesh/index.js +++ /dev/null @@ -1,16 +0,0 @@ -/** - * @file Main export of the PIXI extras library - * @author Mat Groves - * @copyright 2013-2015 GoodBoyDigital - * @license {@link https://github.com/GoodBoyDigital/pixi.js/blob/master/LICENSE|MIT License} - */ - -/** - * @namespace PIXI.extras - */ -module.exports = { - Mesh: require('./Mesh'), - Rope: require('./Rope'), - MeshRenderer: require('./webgl/MeshRenderer'), - MeshShader: require('./webgl/MeshShader') -}; diff --git a/src/extras/mesh/webgl/MeshRenderer.js b/src/extras/mesh/webgl/MeshRenderer.js deleted file mode 100644 index 2dd7678..0000000 --- a/src/extras/mesh/webgl/MeshRenderer.js +++ /dev/null @@ -1,215 +0,0 @@ -var ObjectRenderer = require('../../../core/renderers/webgl/utils/ObjectRenderer'), - WebGLRenderer = require('../../../core/renderers/webgl/WebGLRenderer'); - -/** - * @author Mat Groves - * - * Big thanks to the very clever Matt DesLauriers https://github.com/mattdesl/ - * for creating the original pixi version! - * Also a thanks to https://github.com/bchevalier for tweaking the tint and alpha so that they now share 4 bytes on the vertex buffer - * - * Heavily inspired by LibGDX's MeshRenderer: - * https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/graphics/g2d/MeshRenderer.java - */ - -/** - * - * @class - * @private - * @memberof PIXI - * @extends ObjectRenderer - * @param renderer {WebGLRenderer} The renderer this sprite batch works for. - */ -function MeshRenderer(renderer) -{ - ObjectRenderer.call(this, renderer); - - - /** - * Holds the indices - * - * @member {Uint16Array} - */ - this.indices = new Uint16Array(15000); - - //TODO this could be a single buffer shared amongst all renderers as we reuse this set up in most renderers - for (var i=0, j=0; i < 15000; i += 6, j += 4) - { - this.indices[i + 0] = j + 0; - this.indices[i + 1] = j + 1; - this.indices[i + 2] = j + 2; - this.indices[i + 3] = j + 0; - this.indices[i + 4] = j + 2; - this.indices[i + 5] = j + 3; - } -} - -MeshRenderer.prototype = Object.create(ObjectRenderer.prototype); -MeshRenderer.prototype.constructor = MeshRenderer; -module.exports = MeshRenderer; - -WebGLRenderer.registerPlugin('mesh', MeshRenderer); - -/** - * Sets up the renderer context and necessary buffers. - * - * @private - * @param gl {WebGLRenderingContext} the current WebGL drawing context - */ -MeshRenderer.prototype.onContextChange = function () -{ - -}; - -/** - * Renders the sprite object. - * - * @param mesh {Mesh} the mesh to render - */ -MeshRenderer.prototype.render = function (mesh) -{ -// return; - if(!mesh._vertexBuffer) - { - this._initWebGL(mesh); - } - - var renderer = this.renderer, - gl = renderer.gl, - texture = mesh.texture.baseTexture, - shader = renderer.shaderManager.plugins.meshShader; - -// var drawMode = mesh.drawMode === Strip.DRAW_MODES.TRIANGLE_STRIP ? gl.TRIANGLE_STRIP : gl.TRIANGLES; - var drawMode = gl.TRIANGLE_STRIP; - - renderer.blendModeManager.setBlendMode(mesh.blendMode); - - - // set uniforms - gl.uniformMatrix3fv(shader.uniforms.translationMatrix._location, false, mesh.worldTransform.toArray(true)); - - gl.uniformMatrix3fv(shader.uniforms.projectionMatrix._location, false, renderer.currentRenderTarget.projectionMatrix.toArray(true)); - gl.uniform1f(shader.uniforms.alpha._location, mesh.worldAlpha); - - if (!mesh.dirty) - { - - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._vertexBuffer); - gl.bufferSubData(gl.ARRAY_BUFFER, 0, mesh.vertices); - gl.vertexAttribPointer(shader.attributes.aVertexPosition, 2, gl.FLOAT, false, 0, 0); - - - // update the uvs - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._uvBuffer); - gl.vertexAttribPointer(shader.attributes.aTextureCoord, 2, gl.FLOAT, false, 0, 0); - - - gl.activeTexture(gl.TEXTURE0); - - if (!texture._glTextures[gl.id]) - { - this.renderer.updateTexture(texture); - } - else - { - // bind the current texture - gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]); - } - } - else - { - - mesh.dirty = false; - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER, mesh.vertices, gl.STATIC_DRAW); - gl.vertexAttribPointer(shader.attributes.aVertexPosition, 2, gl.FLOAT, false, 0, 0); - - // update the uvs - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._uvBuffer); - gl.bufferData(gl.ARRAY_BUFFER, mesh.uvs, gl.STATIC_DRAW); - gl.vertexAttribPointer(shader.attributes.aTextureCoord, 2, gl.FLOAT, false, 0, 0); - - gl.activeTexture(gl.TEXTURE0); - - if (!texture._glTextures[gl.id]) - { - this.renderer.updateTexture(texture); - } - else - { - // bind the current texture - gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]); - } - - // dont need to upload! - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, mesh._indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, mesh.indices, gl.STATIC_DRAW); - - } - - gl.drawElements(drawMode, mesh.indices.length, gl.UNSIGNED_SHORT, 0); - -}; - -/** - * Prepares all the buffers to render this mesh - * @param mesh {Mesh} the mesh to render - */ -MeshRenderer.prototype._initWebGL = function (mesh) -{ - // build the strip! - var gl = this.renderer.gl; - - mesh._vertexBuffer = gl.createBuffer(); - mesh._indexBuffer = gl.createBuffer(); - mesh._uvBuffer = gl.createBuffer(); - mesh._colorBuffer = gl.createBuffer(); - - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER, mesh.vertices, gl.DYNAMIC_DRAW); - - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._uvBuffer); - gl.bufferData(gl.ARRAY_BUFFER, mesh.uvs, gl.STATIC_DRAW); - - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._colorBuffer); - gl.bufferData(gl.ARRAY_BUFFER, mesh.colors, gl.STATIC_DRAW); - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, mesh._indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, mesh.indices, gl.STATIC_DRAW); -}; - - -/** - * Empties the current batch. - * - */ -MeshRenderer.prototype.flush = function () -{ - -}; - -/** - * Starts a new mesh renderer. - * - */ -MeshRenderer.prototype.start = function () -{ - var gl = this.renderer.gl, - shader = this.renderer.shaderManager.plugins.meshShader; - - this.renderer.shaderManager.setShader(shader); - - // dont need to upload! - //gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indices); - - - // this.s -}; - -/** - * Destroys the Mesh renderer - * - */ -MeshRenderer.prototype.destroy = function () -{ -}; diff --git a/src/extras/index.js b/src/extras/index.js index 267e97c..6f14e0d 100644 --- a/src/extras/index.js +++ b/src/extras/index.js @@ -11,7 +11,6 @@ module.exports = { MovieClip: require('./MovieClip'), TilingSprite: require('./TilingSprite'), - mesh: require('./mesh/index'), cacheAsBitmap: require('./cacheAsBitmap'), getChildByName: require('./getChildByName') }; diff --git a/src/extras/mesh/Mesh.js b/src/extras/mesh/Mesh.js deleted file mode 100644 index 30431ae..0000000 --- a/src/extras/mesh/Mesh.js +++ /dev/null @@ -1,387 +0,0 @@ -var core = require('../../core'); - -/** - * Base mesh class - * @class - * @extends Container - * @memberof PIXI.extras - * @param texture {Texture} The texture to use - * @param [vertices] {Float32Arrif you want to specify the vertices - * @param [uvs] {Float32Array} if you want to specify the uvs - * @param [indices] {Uint16Array} if you want to specify the indices - * @param [drawMode] {number} the drawMode, can be any of the Mesh.DRAW_MODES consts - */ -function Mesh(texture, vertices, uvs, indices, drawMode) -{ - core.Container.call(this); - - /** - * The texture of the Mesh - * - * @member {Texture} - */ - this.texture = texture; - - /** - * The Uvs of the Mesh - * - * @member {Float32Array} - */ - this.uvs = uvs || new Float32Array([0, 1, - 1, 1, - 1, 0, - 0, 1]); - - /** - * An array of vertices - * - * @member {Float32Array} - */ - this.vertices = vertices || new Float32Array([0, 0, - 100, 0, - 100, 100, - 0, 100]); - - /* - * @member {Uint16Array} An array containing the indices of the vertices - */ - // TODO auto generate this based on draw mode! - this.indices = indices || new Uint16Array([0, 1, 2, 3]); - - /** - * Whether the Mesh is dirty or not - * - * @member {boolean} - */ - this.dirty = true; - - /** - * The blend mode to be applied to the sprite. Set to blendModes.NORMAL to remove any blend mode. - * - * @member {number} - * @default CONST.BLEND_MODES.NORMAL; - */ - this.blendMode = core.CONST.BLEND_MODES.NORMAL; - - /** - * Triangles in canvas mode are automatically antialiased, use this value to force triangles to overlap a bit with each other. - * - * @member {number}= - */ - this.canvasPadding = 0; - - /** - * The way the Mesh should be drawn, can be any of the Mesh.DRAW_MODES consts - * - * @member {number} - */ - this.drawMode = drawMode || Mesh.DRAW_MODES.TRIANGLE_MESH; -} - -// constructor -Mesh.prototype = Object.create(core.Container.prototype); -Mesh.prototype.constructor = Mesh; -module.exports = Mesh; - -/** - * Renders the object using the WebGL renderer - * - * @param renderer {WebGLRenderer} a reference to the WebGL renderer - */ -Mesh.prototype._renderWebGL = function (renderer) -{ - renderer.setObjectRenderer(renderer.plugins.mesh); - renderer.plugins.mesh.render(this); -}; - -/** - * Renders the object using the Canvas renderer - * - * @param renderer {CanvasRenderer} - */ -Mesh.prototype._renderCanvas = function (renderer) -{ - var context = renderer.context; - - var transform = this.worldTransform; - - if (renderer.roundPixels) - { - context.setTransform(transform.a, transform.b, transform.c, transform.d, transform.tx | 0, transform.ty | 0); - } - else - { - context.setTransform(transform.a, transform.b, transform.c, transform.d, transform.tx, transform.ty); - } - - if (this.drawMode === Mesh.DRAW_MODES.TRIANGLE_MESH) - { - this._renderCanvasTriangleMesh(context); - } - else - { - this._renderCanvasTriangles(context); - } -}; - -/** - * Draws the object in Triangle Mesh mode using canvas - * - * @param context {CanvasRenderingContext2D} the current drawing context - * @private - */ -Mesh.prototype._renderCanvasTriangleMesh = function (context) -{ - // draw triangles!! - var vertices = this.vertices; - var uvs = this.uvs; - - var length = vertices.length / 2; - // this.count++; - - for (var i = 0; i < length - 2; i++) - { - // draw some triangles! - var index = i * 2; - this._renderCanvasDrawTriangle(context, vertices, uvs, index, (index + 2), (index + 4)); - } -}; - -/** - * Draws the object in triangle mode using canvas - * - * @param context {CanvasRenderingContext2D} the current drawing context - * @private - */ -Mesh.prototype._renderCanvasTriangles = function (context) -{ - // draw triangles!! - var vertices = this.vertices; - var uvs = this.uvs; - var indices = this.indices; - - var length = indices.length; - // this.count++; - - for (var i = 0; i < length; i += 3) - { - // draw some triangles! - var index0 = indices[i] * 2, index1 = indices[i + 1] * 2, index2 = indices[i + 2] * 2; - this._renderCanvasDrawTriangle(context, vertices, uvs, index0, index1, index2); - } -}; - -/** - * Draws one of the triangles that form this Mesh - * - * @param context {CanvasRenderingContext2D} the current drawing context - * @param vertices {Float32Array} a reference to the vertices of the Mesh - * @param uvs {Float32Array} a reference to the uvs of the Mesh - * @param index0 {number} the index of the first vertex - * @param index1 {number} the index of the second vertex - * @param index2 {number} the index of the third vertex - * @private - */ -Mesh.prototype._renderCanvasDrawTriangle = function (context, vertices, uvs, index0, index1, index2) -{ - var textureSource = this.texture.baseTexture.source; - var textureWidth = this.texture.width; - var textureHeight = this.texture.height; - - var x0 = vertices[index0], x1 = vertices[index1], x2 = vertices[index2]; - var y0 = vertices[index0 + 1], y1 = vertices[index1 + 1], y2 = vertices[index2 + 1]; - - var u0 = uvs[index0] * textureWidth, u1 = uvs[index1] * textureWidth, u2 = uvs[index2] * textureWidth; - var v0 = uvs[index0 + 1] * textureHeight, v1 = uvs[index1 + 1] * textureHeight, v2 = uvs[index2 + 1] * textureHeight; - - if (this.canvasPadding > 0) - { - var paddingX = this.canvasPadding / this.worldTransform.a; - var paddingY = this.canvasPadding / this.worldTransform.d; - var centerX = (x0 + x1 + x2) / 3; - var centerY = (y0 + y1 + y2) / 3; - - var normX = x0 - centerX; - var normY = y0 - centerY; - - var dist = Math.sqrt(normX * normX + normY * normY); - x0 = centerX + (normX / dist) * (dist + paddingX); - y0 = centerY + (normY / dist) * (dist + paddingY); - - // - - normX = x1 - centerX; - normY = y1 - centerY; - - dist = Math.sqrt(normX * normX + normY * normY); - x1 = centerX + (normX / dist) * (dist + paddingX); - y1 = centerY + (normY / dist) * (dist + paddingY); - - normX = x2 - centerX; - normY = y2 - centerY; - - dist = Math.sqrt(normX * normX + normY * normY); - x2 = centerX + (normX / dist) * (dist + paddingX); - y2 = centerY + (normY / dist) * (dist + paddingY); - } - - context.save(); - context.beginPath(); - - - context.moveTo(x0, y0); - context.lineTo(x1, y1); - context.lineTo(x2, y2); - - context.closePath(); - - context.clip(); - - // Compute matrix transform - var delta = (u0 * v1) + (v0 * u2) + (u1 * v2) - (v1 * u2) - (v0 * u1) - (u0 * v2); - var deltaA = (x0 * v1) + (v0 * x2) + (x1 * v2) - (v1 * x2) - (v0 * x1) - (x0 * v2); - var deltaB = (u0 * x1) + (x0 * u2) + (u1 * x2) - (x1 * u2) - (x0 * u1) - (u0 * x2); - var deltaC = (u0 * v1 * x2) + (v0 * x1 * u2) + (x0 * u1 * v2) - (x0 * v1 * u2) - (v0 * u1 * x2) - (u0 * x1 * v2); - var deltaD = (y0 * v1) + (v0 * y2) + (y1 * v2) - (v1 * y2) - (v0 * y1) - (y0 * v2); - var deltaE = (u0 * y1) + (y0 * u2) + (u1 * y2) - (y1 * u2) - (y0 * u1) - (u0 * y2); - var deltaF = (u0 * v1 * y2) + (v0 * y1 * u2) + (y0 * u1 * v2) - (y0 * v1 * u2) - (v0 * u1 * y2) - (u0 * y1 * v2); - - context.transform(deltaA / delta, deltaD / delta, - deltaB / delta, deltaE / delta, - deltaC / delta, deltaF / delta); - - context.drawImage(textureSource, 0, 0); - context.restore(); -}; - - - -/** - * Renders a flat Mesh - * - * @param Mesh {Mesh} The Mesh to render - * @private - */ -Mesh.prototype.renderMeshFlat = function (Mesh) -{ - var context = this.context; - var vertices = Mesh.vertices; - - var length = vertices.length/2; - // this.count++; - - context.beginPath(); - for (var i=1; i < length-2; i++) - { - // draw some triangles! - var index = i*2; - - var x0 = vertices[index], x1 = vertices[index+2], x2 = vertices[index+4]; - var y0 = vertices[index+1], y1 = vertices[index+3], y2 = vertices[index+5]; - - context.moveTo(x0, y0); - context.lineTo(x1, y1); - context.lineTo(x2, y2); - } - - context.fillStyle = '#FF0000'; - context.fill(); - context.closePath(); -}; - -/* -Mesh.prototype.setTexture = function (texture) -{ - //TODO SET THE TEXTURES - //TODO VISIBILITY - //TODO SETTER - - // stop current texture - this.texture = texture; - this.width = texture.frame.width; - this.height = texture.frame.height; - this.updateFrame = true; -}; - */ - -/** - * When the texture is updated, this event will fire to update the scale and frame - * - * @param event - * @private - */ - -Mesh.prototype.onTextureUpdate = function () -{ - this.updateFrame = true; -}; - -/** - * Returns the bounds of the mesh as a rectangle. The bounds calculation takes the worldTransform into account. - * - * @param matrix {Matrix} the transformation matrix of the sprite - * @return {Rectangle} the framing rectangle - */ -Mesh.prototype.getBounds = function (matrix) -{ - var worldTransform = matrix || this.worldTransform; - - var a = worldTransform.a; - var b = worldTransform.b; - var c = worldTransform.c; - var d = worldTransform.d; - var tx = worldTransform.tx; - var ty = worldTransform.ty; - - var maxX = -Infinity; - var maxY = -Infinity; - - var minX = Infinity; - var minY = Infinity; - - var vertices = this.vertices; - for (var i = 0, n = vertices.length; i < n; i += 2) - { - var rawX = vertices[i], rawY = vertices[i + 1]; - var x = (a * rawX) + (c * rawY) + tx; - var y = (d * rawY) + (b * rawX) + ty; - - minX = x < minX ? x : minX; - minY = y < minY ? y : minY; - - maxX = x > maxX ? x : maxX; - maxY = y > maxY ? y : maxY; - } - - if (minX === -Infinity || maxY === Infinity) - { - return core.math.Rectangle.EMPTY; - } - - var bounds = this._bounds; - - bounds.x = minX; - bounds.width = maxX - minX; - - bounds.y = minY; - bounds.height = maxY - minY; - - // store a reference so that if this function gets called again in the render cycle we do not have to recalculate - this._currentBounds = bounds; - - return bounds; -}; - -/** - * Different drawing buffer modes supported - * - * @static - * @constant - * @property {object} DRAW_MODES - * @property {number} DRAW_MODES.TRIANGLE_MESH - * @property {number} DRAW_MODES.TRIANGLES - */ -Mesh.DRAW_MODES = { - TRIANGLE_MESH: 0, - TRIANGLES: 1 -}; diff --git a/src/extras/mesh/Rope.js b/src/extras/mesh/Rope.js deleted file mode 100644 index 8119995..0000000 --- a/src/extras/mesh/Rope.js +++ /dev/null @@ -1,192 +0,0 @@ -var Mesh = require('./Mesh'); - -/** - * The rope allows you to draw a texture across several points and them manipulate these points - * - *```js - * for (var i = 0; i < 20; i++) { - * points.push(new PIXI.Point(i * 50, 0)); - * }; - * var rope = new PIXI.Rope(PIXI.Texture.fromImage("snake.png"), points); - * ``` - * - * @class - * @extends Mesh - * @memberof PIXI.extras - * @param {Texture} texture - The texture to use on the rope. - * @param {Array} points - An array of {Point} objects to construct this rope. - * - */ -function Rope(texture, points) -{ - Mesh.call(this, texture); - - /* - * @member {Array} An array of points that determine the rope - */ - this.points = points; - - /* - * @member {Float32Array} An array of vertices used to construct this rope. - */ - this.vertices = new Float32Array(points.length * 4); - - /* - * @member {Float32Array} The WebGL Uvs of the rope. - */ - this.uvs = new Float32Array(points.length * 4); - - /* - * @member {Float32Array} An array containing the color components - */ - this.colors = new Float32Array(points.length * 2); - - /* - * @member {Uint16Array} An array containing the indices of the vertices - */ - this.indices = new Uint16Array(points.length * 2); - - this.refresh(); -} - - -// constructor -Rope.prototype = Object.create(Mesh.prototype); -Rope.prototype.constructor = Rope; -module.exports = Rope; - -/** - * Refreshes - * - */ -Rope.prototype.refresh = function () -{ - var points = this.points; - - if (points.length < 1) - { - return; - } - - var uvs = this.uvs; - - var indices = this.indices; - var colors = this.colors; - - // this.count -= 0.2; - - uvs[0] = 0; - uvs[1] = 0; - uvs[2] = 0; - uvs[3] = 1; - - colors[0] = 1; - colors[1] = 1; - - indices[0] = 0; - indices[1] = 1; - - var total = points.length, - point, index, amount; - - for (var i = 1; i < total; i++) - { - point = points[i]; - index = i * 4; - // time to do some smart drawing! - amount = i / (total-1); - - if (i%2) - { - uvs[index] = amount; - uvs[index+1] = 0; - - uvs[index+2] = amount; - uvs[index+3] = 1; - } - else - { - uvs[index] = amount; - uvs[index+1] = 0; - - uvs[index+2] = amount; - uvs[index+3] = 1; - } - - index = i * 2; - colors[index] = 1; - colors[index+1] = 1; - - index = i * 2; - indices[index] = index; - indices[index + 1] = index + 1; - } -}; - -/* - * Updates the object transform for rendering - * - * @private - */ -Rope.prototype.updateTransform = function () -{ - var points = this.points; - - if (points.length < 1) - { - return; - } - - var lastPoint = points[0]; - var nextPoint; - var perpX = 0; - var perpY = 0; - - // this.count -= 0.2; - - var vertices = this.vertices; - var total = points.length, - point, index, ratio, perpLength, num; - - for (var i = 0; i < total; i++) - { - point = points[i]; - index = i * 4; - - if (i < points.length-1) - { - nextPoint = points[i+1]; - } - else - { - nextPoint = point; - } - - perpY = -(nextPoint.x - lastPoint.x); - perpX = nextPoint.y - lastPoint.y; - - ratio = (1 - (i / (total-1))) * 10; - - if (ratio > 1) - { - ratio = 1; - } - - perpLength = Math.sqrt(perpX * perpX + perpY * perpY); - num = this.texture.height / 2; //(20 + Math.abs(Math.sin((i + this.count) * 0.3) * 50) )* ratio; - perpX /= perpLength; - perpY /= perpLength; - - perpX *= num; - perpY *= num; - - vertices[index] = point.x + perpX; - vertices[index+1] = point.y + perpY; - vertices[index+2] = point.x - perpX; - vertices[index+3] = point.y - perpY; - - lastPoint = point; - } - - this.containerUpdateTransform(); -}; diff --git a/src/extras/mesh/index.js b/src/extras/mesh/index.js deleted file mode 100644 index dd37f87..0000000 --- a/src/extras/mesh/index.js +++ /dev/null @@ -1,16 +0,0 @@ -/** - * @file Main export of the PIXI extras library - * @author Mat Groves - * @copyright 2013-2015 GoodBoyDigital - * @license {@link https://github.com/GoodBoyDigital/pixi.js/blob/master/LICENSE|MIT License} - */ - -/** - * @namespace PIXI.extras - */ -module.exports = { - Mesh: require('./Mesh'), - Rope: require('./Rope'), - MeshRenderer: require('./webgl/MeshRenderer'), - MeshShader: require('./webgl/MeshShader') -}; diff --git a/src/extras/mesh/webgl/MeshRenderer.js b/src/extras/mesh/webgl/MeshRenderer.js deleted file mode 100644 index 2dd7678..0000000 --- a/src/extras/mesh/webgl/MeshRenderer.js +++ /dev/null @@ -1,215 +0,0 @@ -var ObjectRenderer = require('../../../core/renderers/webgl/utils/ObjectRenderer'), - WebGLRenderer = require('../../../core/renderers/webgl/WebGLRenderer'); - -/** - * @author Mat Groves - * - * Big thanks to the very clever Matt DesLauriers https://github.com/mattdesl/ - * for creating the original pixi version! - * Also a thanks to https://github.com/bchevalier for tweaking the tint and alpha so that they now share 4 bytes on the vertex buffer - * - * Heavily inspired by LibGDX's MeshRenderer: - * https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/graphics/g2d/MeshRenderer.java - */ - -/** - * - * @class - * @private - * @memberof PIXI - * @extends ObjectRenderer - * @param renderer {WebGLRenderer} The renderer this sprite batch works for. - */ -function MeshRenderer(renderer) -{ - ObjectRenderer.call(this, renderer); - - - /** - * Holds the indices - * - * @member {Uint16Array} - */ - this.indices = new Uint16Array(15000); - - //TODO this could be a single buffer shared amongst all renderers as we reuse this set up in most renderers - for (var i=0, j=0; i < 15000; i += 6, j += 4) - { - this.indices[i + 0] = j + 0; - this.indices[i + 1] = j + 1; - this.indices[i + 2] = j + 2; - this.indices[i + 3] = j + 0; - this.indices[i + 4] = j + 2; - this.indices[i + 5] = j + 3; - } -} - -MeshRenderer.prototype = Object.create(ObjectRenderer.prototype); -MeshRenderer.prototype.constructor = MeshRenderer; -module.exports = MeshRenderer; - -WebGLRenderer.registerPlugin('mesh', MeshRenderer); - -/** - * Sets up the renderer context and necessary buffers. - * - * @private - * @param gl {WebGLRenderingContext} the current WebGL drawing context - */ -MeshRenderer.prototype.onContextChange = function () -{ - -}; - -/** - * Renders the sprite object. - * - * @param mesh {Mesh} the mesh to render - */ -MeshRenderer.prototype.render = function (mesh) -{ -// return; - if(!mesh._vertexBuffer) - { - this._initWebGL(mesh); - } - - var renderer = this.renderer, - gl = renderer.gl, - texture = mesh.texture.baseTexture, - shader = renderer.shaderManager.plugins.meshShader; - -// var drawMode = mesh.drawMode === Strip.DRAW_MODES.TRIANGLE_STRIP ? gl.TRIANGLE_STRIP : gl.TRIANGLES; - var drawMode = gl.TRIANGLE_STRIP; - - renderer.blendModeManager.setBlendMode(mesh.blendMode); - - - // set uniforms - gl.uniformMatrix3fv(shader.uniforms.translationMatrix._location, false, mesh.worldTransform.toArray(true)); - - gl.uniformMatrix3fv(shader.uniforms.projectionMatrix._location, false, renderer.currentRenderTarget.projectionMatrix.toArray(true)); - gl.uniform1f(shader.uniforms.alpha._location, mesh.worldAlpha); - - if (!mesh.dirty) - { - - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._vertexBuffer); - gl.bufferSubData(gl.ARRAY_BUFFER, 0, mesh.vertices); - gl.vertexAttribPointer(shader.attributes.aVertexPosition, 2, gl.FLOAT, false, 0, 0); - - - // update the uvs - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._uvBuffer); - gl.vertexAttribPointer(shader.attributes.aTextureCoord, 2, gl.FLOAT, false, 0, 0); - - - gl.activeTexture(gl.TEXTURE0); - - if (!texture._glTextures[gl.id]) - { - this.renderer.updateTexture(texture); - } - else - { - // bind the current texture - gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]); - } - } - else - { - - mesh.dirty = false; - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER, mesh.vertices, gl.STATIC_DRAW); - gl.vertexAttribPointer(shader.attributes.aVertexPosition, 2, gl.FLOAT, false, 0, 0); - - // update the uvs - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._uvBuffer); - gl.bufferData(gl.ARRAY_BUFFER, mesh.uvs, gl.STATIC_DRAW); - gl.vertexAttribPointer(shader.attributes.aTextureCoord, 2, gl.FLOAT, false, 0, 0); - - gl.activeTexture(gl.TEXTURE0); - - if (!texture._glTextures[gl.id]) - { - this.renderer.updateTexture(texture); - } - else - { - // bind the current texture - gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]); - } - - // dont need to upload! - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, mesh._indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, mesh.indices, gl.STATIC_DRAW); - - } - - gl.drawElements(drawMode, mesh.indices.length, gl.UNSIGNED_SHORT, 0); - -}; - -/** - * Prepares all the buffers to render this mesh - * @param mesh {Mesh} the mesh to render - */ -MeshRenderer.prototype._initWebGL = function (mesh) -{ - // build the strip! - var gl = this.renderer.gl; - - mesh._vertexBuffer = gl.createBuffer(); - mesh._indexBuffer = gl.createBuffer(); - mesh._uvBuffer = gl.createBuffer(); - mesh._colorBuffer = gl.createBuffer(); - - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER, mesh.vertices, gl.DYNAMIC_DRAW); - - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._uvBuffer); - gl.bufferData(gl.ARRAY_BUFFER, mesh.uvs, gl.STATIC_DRAW); - - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._colorBuffer); - gl.bufferData(gl.ARRAY_BUFFER, mesh.colors, gl.STATIC_DRAW); - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, mesh._indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, mesh.indices, gl.STATIC_DRAW); -}; - - -/** - * Empties the current batch. - * - */ -MeshRenderer.prototype.flush = function () -{ - -}; - -/** - * Starts a new mesh renderer. - * - */ -MeshRenderer.prototype.start = function () -{ - var gl = this.renderer.gl, - shader = this.renderer.shaderManager.plugins.meshShader; - - this.renderer.shaderManager.setShader(shader); - - // dont need to upload! - //gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indices); - - - // this.s -}; - -/** - * Destroys the Mesh renderer - * - */ -MeshRenderer.prototype.destroy = function () -{ -}; diff --git a/src/extras/mesh/webgl/MeshShader.js b/src/extras/mesh/webgl/MeshShader.js deleted file mode 100644 index 51c03f5..0000000 --- a/src/extras/mesh/webgl/MeshShader.js +++ /dev/null @@ -1,59 +0,0 @@ -var core = require('../../../core'); - -/** - * @class - * @extends Shader - * @memberof PIXI.extras - * @param shaderManager {ShaderManager} The WebGL shader manager this shader works for. - */ -function StripShader(shaderManager) -{ - core.Shader.call(this, - shaderManager, - // vertex shader - [ - 'precision lowp float;', - 'attribute vec2 aVertexPosition;', - 'attribute vec2 aTextureCoord;', - - 'uniform mat3 translationMatrix;', - 'uniform mat3 projectionMatrix;', - - 'varying vec2 vTextureCoord;', - - 'void main(void){', - ' gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);', - ' vTextureCoord = aTextureCoord;', - '}' - ].join('\n'), - [ - 'precision lowp float;', - - 'varying vec2 vTextureCoord;', - 'uniform float alpha;', - - 'uniform sampler2D uSampler;', - - 'void main(void){', - ' gl_FragColor = texture2D(uSampler, vTextureCoord) * alpha ;', - '}' - ].join('\n'), - // custom uniforms - { - alpha: { type: '1f', value: 0 }, - translationMatrix: { type: 'mat3', value: new Float32Array(9) }, - projectionMatrix: { type: 'mat3', value: new Float32Array(9) } - }, - // custom attributes - { - aVertexPosition:0, - aTextureCoord:0 - } - ); -} - -StripShader.prototype = Object.create(core.Shader.prototype); -StripShader.prototype.constructor = StripShader; -module.exports = StripShader; - -core.ShaderManager.registerPlugin('meshShader', StripShader); diff --git a/src/extras/index.js b/src/extras/index.js index 267e97c..6f14e0d 100644 --- a/src/extras/index.js +++ b/src/extras/index.js @@ -11,7 +11,6 @@ module.exports = { MovieClip: require('./MovieClip'), TilingSprite: require('./TilingSprite'), - mesh: require('./mesh/index'), cacheAsBitmap: require('./cacheAsBitmap'), getChildByName: require('./getChildByName') }; diff --git a/src/extras/mesh/Mesh.js b/src/extras/mesh/Mesh.js deleted file mode 100644 index 30431ae..0000000 --- a/src/extras/mesh/Mesh.js +++ /dev/null @@ -1,387 +0,0 @@ -var core = require('../../core'); - -/** - * Base mesh class - * @class - * @extends Container - * @memberof PIXI.extras - * @param texture {Texture} The texture to use - * @param [vertices] {Float32Arrif you want to specify the vertices - * @param [uvs] {Float32Array} if you want to specify the uvs - * @param [indices] {Uint16Array} if you want to specify the indices - * @param [drawMode] {number} the drawMode, can be any of the Mesh.DRAW_MODES consts - */ -function Mesh(texture, vertices, uvs, indices, drawMode) -{ - core.Container.call(this); - - /** - * The texture of the Mesh - * - * @member {Texture} - */ - this.texture = texture; - - /** - * The Uvs of the Mesh - * - * @member {Float32Array} - */ - this.uvs = uvs || new Float32Array([0, 1, - 1, 1, - 1, 0, - 0, 1]); - - /** - * An array of vertices - * - * @member {Float32Array} - */ - this.vertices = vertices || new Float32Array([0, 0, - 100, 0, - 100, 100, - 0, 100]); - - /* - * @member {Uint16Array} An array containing the indices of the vertices - */ - // TODO auto generate this based on draw mode! - this.indices = indices || new Uint16Array([0, 1, 2, 3]); - - /** - * Whether the Mesh is dirty or not - * - * @member {boolean} - */ - this.dirty = true; - - /** - * The blend mode to be applied to the sprite. Set to blendModes.NORMAL to remove any blend mode. - * - * @member {number} - * @default CONST.BLEND_MODES.NORMAL; - */ - this.blendMode = core.CONST.BLEND_MODES.NORMAL; - - /** - * Triangles in canvas mode are automatically antialiased, use this value to force triangles to overlap a bit with each other. - * - * @member {number}= - */ - this.canvasPadding = 0; - - /** - * The way the Mesh should be drawn, can be any of the Mesh.DRAW_MODES consts - * - * @member {number} - */ - this.drawMode = drawMode || Mesh.DRAW_MODES.TRIANGLE_MESH; -} - -// constructor -Mesh.prototype = Object.create(core.Container.prototype); -Mesh.prototype.constructor = Mesh; -module.exports = Mesh; - -/** - * Renders the object using the WebGL renderer - * - * @param renderer {WebGLRenderer} a reference to the WebGL renderer - */ -Mesh.prototype._renderWebGL = function (renderer) -{ - renderer.setObjectRenderer(renderer.plugins.mesh); - renderer.plugins.mesh.render(this); -}; - -/** - * Renders the object using the Canvas renderer - * - * @param renderer {CanvasRenderer} - */ -Mesh.prototype._renderCanvas = function (renderer) -{ - var context = renderer.context; - - var transform = this.worldTransform; - - if (renderer.roundPixels) - { - context.setTransform(transform.a, transform.b, transform.c, transform.d, transform.tx | 0, transform.ty | 0); - } - else - { - context.setTransform(transform.a, transform.b, transform.c, transform.d, transform.tx, transform.ty); - } - - if (this.drawMode === Mesh.DRAW_MODES.TRIANGLE_MESH) - { - this._renderCanvasTriangleMesh(context); - } - else - { - this._renderCanvasTriangles(context); - } -}; - -/** - * Draws the object in Triangle Mesh mode using canvas - * - * @param context {CanvasRenderingContext2D} the current drawing context - * @private - */ -Mesh.prototype._renderCanvasTriangleMesh = function (context) -{ - // draw triangles!! - var vertices = this.vertices; - var uvs = this.uvs; - - var length = vertices.length / 2; - // this.count++; - - for (var i = 0; i < length - 2; i++) - { - // draw some triangles! - var index = i * 2; - this._renderCanvasDrawTriangle(context, vertices, uvs, index, (index + 2), (index + 4)); - } -}; - -/** - * Draws the object in triangle mode using canvas - * - * @param context {CanvasRenderingContext2D} the current drawing context - * @private - */ -Mesh.prototype._renderCanvasTriangles = function (context) -{ - // draw triangles!! - var vertices = this.vertices; - var uvs = this.uvs; - var indices = this.indices; - - var length = indices.length; - // this.count++; - - for (var i = 0; i < length; i += 3) - { - // draw some triangles! - var index0 = indices[i] * 2, index1 = indices[i + 1] * 2, index2 = indices[i + 2] * 2; - this._renderCanvasDrawTriangle(context, vertices, uvs, index0, index1, index2); - } -}; - -/** - * Draws one of the triangles that form this Mesh - * - * @param context {CanvasRenderingContext2D} the current drawing context - * @param vertices {Float32Array} a reference to the vertices of the Mesh - * @param uvs {Float32Array} a reference to the uvs of the Mesh - * @param index0 {number} the index of the first vertex - * @param index1 {number} the index of the second vertex - * @param index2 {number} the index of the third vertex - * @private - */ -Mesh.prototype._renderCanvasDrawTriangle = function (context, vertices, uvs, index0, index1, index2) -{ - var textureSource = this.texture.baseTexture.source; - var textureWidth = this.texture.width; - var textureHeight = this.texture.height; - - var x0 = vertices[index0], x1 = vertices[index1], x2 = vertices[index2]; - var y0 = vertices[index0 + 1], y1 = vertices[index1 + 1], y2 = vertices[index2 + 1]; - - var u0 = uvs[index0] * textureWidth, u1 = uvs[index1] * textureWidth, u2 = uvs[index2] * textureWidth; - var v0 = uvs[index0 + 1] * textureHeight, v1 = uvs[index1 + 1] * textureHeight, v2 = uvs[index2 + 1] * textureHeight; - - if (this.canvasPadding > 0) - { - var paddingX = this.canvasPadding / this.worldTransform.a; - var paddingY = this.canvasPadding / this.worldTransform.d; - var centerX = (x0 + x1 + x2) / 3; - var centerY = (y0 + y1 + y2) / 3; - - var normX = x0 - centerX; - var normY = y0 - centerY; - - var dist = Math.sqrt(normX * normX + normY * normY); - x0 = centerX + (normX / dist) * (dist + paddingX); - y0 = centerY + (normY / dist) * (dist + paddingY); - - // - - normX = x1 - centerX; - normY = y1 - centerY; - - dist = Math.sqrt(normX * normX + normY * normY); - x1 = centerX + (normX / dist) * (dist + paddingX); - y1 = centerY + (normY / dist) * (dist + paddingY); - - normX = x2 - centerX; - normY = y2 - centerY; - - dist = Math.sqrt(normX * normX + normY * normY); - x2 = centerX + (normX / dist) * (dist + paddingX); - y2 = centerY + (normY / dist) * (dist + paddingY); - } - - context.save(); - context.beginPath(); - - - context.moveTo(x0, y0); - context.lineTo(x1, y1); - context.lineTo(x2, y2); - - context.closePath(); - - context.clip(); - - // Compute matrix transform - var delta = (u0 * v1) + (v0 * u2) + (u1 * v2) - (v1 * u2) - (v0 * u1) - (u0 * v2); - var deltaA = (x0 * v1) + (v0 * x2) + (x1 * v2) - (v1 * x2) - (v0 * x1) - (x0 * v2); - var deltaB = (u0 * x1) + (x0 * u2) + (u1 * x2) - (x1 * u2) - (x0 * u1) - (u0 * x2); - var deltaC = (u0 * v1 * x2) + (v0 * x1 * u2) + (x0 * u1 * v2) - (x0 * v1 * u2) - (v0 * u1 * x2) - (u0 * x1 * v2); - var deltaD = (y0 * v1) + (v0 * y2) + (y1 * v2) - (v1 * y2) - (v0 * y1) - (y0 * v2); - var deltaE = (u0 * y1) + (y0 * u2) + (u1 * y2) - (y1 * u2) - (y0 * u1) - (u0 * y2); - var deltaF = (u0 * v1 * y2) + (v0 * y1 * u2) + (y0 * u1 * v2) - (y0 * v1 * u2) - (v0 * u1 * y2) - (u0 * y1 * v2); - - context.transform(deltaA / delta, deltaD / delta, - deltaB / delta, deltaE / delta, - deltaC / delta, deltaF / delta); - - context.drawImage(textureSource, 0, 0); - context.restore(); -}; - - - -/** - * Renders a flat Mesh - * - * @param Mesh {Mesh} The Mesh to render - * @private - */ -Mesh.prototype.renderMeshFlat = function (Mesh) -{ - var context = this.context; - var vertices = Mesh.vertices; - - var length = vertices.length/2; - // this.count++; - - context.beginPath(); - for (var i=1; i < length-2; i++) - { - // draw some triangles! - var index = i*2; - - var x0 = vertices[index], x1 = vertices[index+2], x2 = vertices[index+4]; - var y0 = vertices[index+1], y1 = vertices[index+3], y2 = vertices[index+5]; - - context.moveTo(x0, y0); - context.lineTo(x1, y1); - context.lineTo(x2, y2); - } - - context.fillStyle = '#FF0000'; - context.fill(); - context.closePath(); -}; - -/* -Mesh.prototype.setTexture = function (texture) -{ - //TODO SET THE TEXTURES - //TODO VISIBILITY - //TODO SETTER - - // stop current texture - this.texture = texture; - this.width = texture.frame.width; - this.height = texture.frame.height; - this.updateFrame = true; -}; - */ - -/** - * When the texture is updated, this event will fire to update the scale and frame - * - * @param event - * @private - */ - -Mesh.prototype.onTextureUpdate = function () -{ - this.updateFrame = true; -}; - -/** - * Returns the bounds of the mesh as a rectangle. The bounds calculation takes the worldTransform into account. - * - * @param matrix {Matrix} the transformation matrix of the sprite - * @return {Rectangle} the framing rectangle - */ -Mesh.prototype.getBounds = function (matrix) -{ - var worldTransform = matrix || this.worldTransform; - - var a = worldTransform.a; - var b = worldTransform.b; - var c = worldTransform.c; - var d = worldTransform.d; - var tx = worldTransform.tx; - var ty = worldTransform.ty; - - var maxX = -Infinity; - var maxY = -Infinity; - - var minX = Infinity; - var minY = Infinity; - - var vertices = this.vertices; - for (var i = 0, n = vertices.length; i < n; i += 2) - { - var rawX = vertices[i], rawY = vertices[i + 1]; - var x = (a * rawX) + (c * rawY) + tx; - var y = (d * rawY) + (b * rawX) + ty; - - minX = x < minX ? x : minX; - minY = y < minY ? y : minY; - - maxX = x > maxX ? x : maxX; - maxY = y > maxY ? y : maxY; - } - - if (minX === -Infinity || maxY === Infinity) - { - return core.math.Rectangle.EMPTY; - } - - var bounds = this._bounds; - - bounds.x = minX; - bounds.width = maxX - minX; - - bounds.y = minY; - bounds.height = maxY - minY; - - // store a reference so that if this function gets called again in the render cycle we do not have to recalculate - this._currentBounds = bounds; - - return bounds; -}; - -/** - * Different drawing buffer modes supported - * - * @static - * @constant - * @property {object} DRAW_MODES - * @property {number} DRAW_MODES.TRIANGLE_MESH - * @property {number} DRAW_MODES.TRIANGLES - */ -Mesh.DRAW_MODES = { - TRIANGLE_MESH: 0, - TRIANGLES: 1 -}; diff --git a/src/extras/mesh/Rope.js b/src/extras/mesh/Rope.js deleted file mode 100644 index 8119995..0000000 --- a/src/extras/mesh/Rope.js +++ /dev/null @@ -1,192 +0,0 @@ -var Mesh = require('./Mesh'); - -/** - * The rope allows you to draw a texture across several points and them manipulate these points - * - *```js - * for (var i = 0; i < 20; i++) { - * points.push(new PIXI.Point(i * 50, 0)); - * }; - * var rope = new PIXI.Rope(PIXI.Texture.fromImage("snake.png"), points); - * ``` - * - * @class - * @extends Mesh - * @memberof PIXI.extras - * @param {Texture} texture - The texture to use on the rope. - * @param {Array} points - An array of {Point} objects to construct this rope. - * - */ -function Rope(texture, points) -{ - Mesh.call(this, texture); - - /* - * @member {Array} An array of points that determine the rope - */ - this.points = points; - - /* - * @member {Float32Array} An array of vertices used to construct this rope. - */ - this.vertices = new Float32Array(points.length * 4); - - /* - * @member {Float32Array} The WebGL Uvs of the rope. - */ - this.uvs = new Float32Array(points.length * 4); - - /* - * @member {Float32Array} An array containing the color components - */ - this.colors = new Float32Array(points.length * 2); - - /* - * @member {Uint16Array} An array containing the indices of the vertices - */ - this.indices = new Uint16Array(points.length * 2); - - this.refresh(); -} - - -// constructor -Rope.prototype = Object.create(Mesh.prototype); -Rope.prototype.constructor = Rope; -module.exports = Rope; - -/** - * Refreshes - * - */ -Rope.prototype.refresh = function () -{ - var points = this.points; - - if (points.length < 1) - { - return; - } - - var uvs = this.uvs; - - var indices = this.indices; - var colors = this.colors; - - // this.count -= 0.2; - - uvs[0] = 0; - uvs[1] = 0; - uvs[2] = 0; - uvs[3] = 1; - - colors[0] = 1; - colors[1] = 1; - - indices[0] = 0; - indices[1] = 1; - - var total = points.length, - point, index, amount; - - for (var i = 1; i < total; i++) - { - point = points[i]; - index = i * 4; - // time to do some smart drawing! - amount = i / (total-1); - - if (i%2) - { - uvs[index] = amount; - uvs[index+1] = 0; - - uvs[index+2] = amount; - uvs[index+3] = 1; - } - else - { - uvs[index] = amount; - uvs[index+1] = 0; - - uvs[index+2] = amount; - uvs[index+3] = 1; - } - - index = i * 2; - colors[index] = 1; - colors[index+1] = 1; - - index = i * 2; - indices[index] = index; - indices[index + 1] = index + 1; - } -}; - -/* - * Updates the object transform for rendering - * - * @private - */ -Rope.prototype.updateTransform = function () -{ - var points = this.points; - - if (points.length < 1) - { - return; - } - - var lastPoint = points[0]; - var nextPoint; - var perpX = 0; - var perpY = 0; - - // this.count -= 0.2; - - var vertices = this.vertices; - var total = points.length, - point, index, ratio, perpLength, num; - - for (var i = 0; i < total; i++) - { - point = points[i]; - index = i * 4; - - if (i < points.length-1) - { - nextPoint = points[i+1]; - } - else - { - nextPoint = point; - } - - perpY = -(nextPoint.x - lastPoint.x); - perpX = nextPoint.y - lastPoint.y; - - ratio = (1 - (i / (total-1))) * 10; - - if (ratio > 1) - { - ratio = 1; - } - - perpLength = Math.sqrt(perpX * perpX + perpY * perpY); - num = this.texture.height / 2; //(20 + Math.abs(Math.sin((i + this.count) * 0.3) * 50) )* ratio; - perpX /= perpLength; - perpY /= perpLength; - - perpX *= num; - perpY *= num; - - vertices[index] = point.x + perpX; - vertices[index+1] = point.y + perpY; - vertices[index+2] = point.x - perpX; - vertices[index+3] = point.y - perpY; - - lastPoint = point; - } - - this.containerUpdateTransform(); -}; diff --git a/src/extras/mesh/index.js b/src/extras/mesh/index.js deleted file mode 100644 index dd37f87..0000000 --- a/src/extras/mesh/index.js +++ /dev/null @@ -1,16 +0,0 @@ -/** - * @file Main export of the PIXI extras library - * @author Mat Groves - * @copyright 2013-2015 GoodBoyDigital - * @license {@link https://github.com/GoodBoyDigital/pixi.js/blob/master/LICENSE|MIT License} - */ - -/** - * @namespace PIXI.extras - */ -module.exports = { - Mesh: require('./Mesh'), - Rope: require('./Rope'), - MeshRenderer: require('./webgl/MeshRenderer'), - MeshShader: require('./webgl/MeshShader') -}; diff --git a/src/extras/mesh/webgl/MeshRenderer.js b/src/extras/mesh/webgl/MeshRenderer.js deleted file mode 100644 index 2dd7678..0000000 --- a/src/extras/mesh/webgl/MeshRenderer.js +++ /dev/null @@ -1,215 +0,0 @@ -var ObjectRenderer = require('../../../core/renderers/webgl/utils/ObjectRenderer'), - WebGLRenderer = require('../../../core/renderers/webgl/WebGLRenderer'); - -/** - * @author Mat Groves - * - * Big thanks to the very clever Matt DesLauriers https://github.com/mattdesl/ - * for creating the original pixi version! - * Also a thanks to https://github.com/bchevalier for tweaking the tint and alpha so that they now share 4 bytes on the vertex buffer - * - * Heavily inspired by LibGDX's MeshRenderer: - * https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/graphics/g2d/MeshRenderer.java - */ - -/** - * - * @class - * @private - * @memberof PIXI - * @extends ObjectRenderer - * @param renderer {WebGLRenderer} The renderer this sprite batch works for. - */ -function MeshRenderer(renderer) -{ - ObjectRenderer.call(this, renderer); - - - /** - * Holds the indices - * - * @member {Uint16Array} - */ - this.indices = new Uint16Array(15000); - - //TODO this could be a single buffer shared amongst all renderers as we reuse this set up in most renderers - for (var i=0, j=0; i < 15000; i += 6, j += 4) - { - this.indices[i + 0] = j + 0; - this.indices[i + 1] = j + 1; - this.indices[i + 2] = j + 2; - this.indices[i + 3] = j + 0; - this.indices[i + 4] = j + 2; - this.indices[i + 5] = j + 3; - } -} - -MeshRenderer.prototype = Object.create(ObjectRenderer.prototype); -MeshRenderer.prototype.constructor = MeshRenderer; -module.exports = MeshRenderer; - -WebGLRenderer.registerPlugin('mesh', MeshRenderer); - -/** - * Sets up the renderer context and necessary buffers. - * - * @private - * @param gl {WebGLRenderingContext} the current WebGL drawing context - */ -MeshRenderer.prototype.onContextChange = function () -{ - -}; - -/** - * Renders the sprite object. - * - * @param mesh {Mesh} the mesh to render - */ -MeshRenderer.prototype.render = function (mesh) -{ -// return; - if(!mesh._vertexBuffer) - { - this._initWebGL(mesh); - } - - var renderer = this.renderer, - gl = renderer.gl, - texture = mesh.texture.baseTexture, - shader = renderer.shaderManager.plugins.meshShader; - -// var drawMode = mesh.drawMode === Strip.DRAW_MODES.TRIANGLE_STRIP ? gl.TRIANGLE_STRIP : gl.TRIANGLES; - var drawMode = gl.TRIANGLE_STRIP; - - renderer.blendModeManager.setBlendMode(mesh.blendMode); - - - // set uniforms - gl.uniformMatrix3fv(shader.uniforms.translationMatrix._location, false, mesh.worldTransform.toArray(true)); - - gl.uniformMatrix3fv(shader.uniforms.projectionMatrix._location, false, renderer.currentRenderTarget.projectionMatrix.toArray(true)); - gl.uniform1f(shader.uniforms.alpha._location, mesh.worldAlpha); - - if (!mesh.dirty) - { - - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._vertexBuffer); - gl.bufferSubData(gl.ARRAY_BUFFER, 0, mesh.vertices); - gl.vertexAttribPointer(shader.attributes.aVertexPosition, 2, gl.FLOAT, false, 0, 0); - - - // update the uvs - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._uvBuffer); - gl.vertexAttribPointer(shader.attributes.aTextureCoord, 2, gl.FLOAT, false, 0, 0); - - - gl.activeTexture(gl.TEXTURE0); - - if (!texture._glTextures[gl.id]) - { - this.renderer.updateTexture(texture); - } - else - { - // bind the current texture - gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]); - } - } - else - { - - mesh.dirty = false; - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER, mesh.vertices, gl.STATIC_DRAW); - gl.vertexAttribPointer(shader.attributes.aVertexPosition, 2, gl.FLOAT, false, 0, 0); - - // update the uvs - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._uvBuffer); - gl.bufferData(gl.ARRAY_BUFFER, mesh.uvs, gl.STATIC_DRAW); - gl.vertexAttribPointer(shader.attributes.aTextureCoord, 2, gl.FLOAT, false, 0, 0); - - gl.activeTexture(gl.TEXTURE0); - - if (!texture._glTextures[gl.id]) - { - this.renderer.updateTexture(texture); - } - else - { - // bind the current texture - gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]); - } - - // dont need to upload! - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, mesh._indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, mesh.indices, gl.STATIC_DRAW); - - } - - gl.drawElements(drawMode, mesh.indices.length, gl.UNSIGNED_SHORT, 0); - -}; - -/** - * Prepares all the buffers to render this mesh - * @param mesh {Mesh} the mesh to render - */ -MeshRenderer.prototype._initWebGL = function (mesh) -{ - // build the strip! - var gl = this.renderer.gl; - - mesh._vertexBuffer = gl.createBuffer(); - mesh._indexBuffer = gl.createBuffer(); - mesh._uvBuffer = gl.createBuffer(); - mesh._colorBuffer = gl.createBuffer(); - - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER, mesh.vertices, gl.DYNAMIC_DRAW); - - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._uvBuffer); - gl.bufferData(gl.ARRAY_BUFFER, mesh.uvs, gl.STATIC_DRAW); - - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._colorBuffer); - gl.bufferData(gl.ARRAY_BUFFER, mesh.colors, gl.STATIC_DRAW); - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, mesh._indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, mesh.indices, gl.STATIC_DRAW); -}; - - -/** - * Empties the current batch. - * - */ -MeshRenderer.prototype.flush = function () -{ - -}; - -/** - * Starts a new mesh renderer. - * - */ -MeshRenderer.prototype.start = function () -{ - var gl = this.renderer.gl, - shader = this.renderer.shaderManager.plugins.meshShader; - - this.renderer.shaderManager.setShader(shader); - - // dont need to upload! - //gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indices); - - - // this.s -}; - -/** - * Destroys the Mesh renderer - * - */ -MeshRenderer.prototype.destroy = function () -{ -}; diff --git a/src/extras/mesh/webgl/MeshShader.js b/src/extras/mesh/webgl/MeshShader.js deleted file mode 100644 index 51c03f5..0000000 --- a/src/extras/mesh/webgl/MeshShader.js +++ /dev/null @@ -1,59 +0,0 @@ -var core = require('../../../core'); - -/** - * @class - * @extends Shader - * @memberof PIXI.extras - * @param shaderManager {ShaderManager} The WebGL shader manager this shader works for. - */ -function StripShader(shaderManager) -{ - core.Shader.call(this, - shaderManager, - // vertex shader - [ - 'precision lowp float;', - 'attribute vec2 aVertexPosition;', - 'attribute vec2 aTextureCoord;', - - 'uniform mat3 translationMatrix;', - 'uniform mat3 projectionMatrix;', - - 'varying vec2 vTextureCoord;', - - 'void main(void){', - ' gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);', - ' vTextureCoord = aTextureCoord;', - '}' - ].join('\n'), - [ - 'precision lowp float;', - - 'varying vec2 vTextureCoord;', - 'uniform float alpha;', - - 'uniform sampler2D uSampler;', - - 'void main(void){', - ' gl_FragColor = texture2D(uSampler, vTextureCoord) * alpha ;', - '}' - ].join('\n'), - // custom uniforms - { - alpha: { type: '1f', value: 0 }, - translationMatrix: { type: 'mat3', value: new Float32Array(9) }, - projectionMatrix: { type: 'mat3', value: new Float32Array(9) } - }, - // custom attributes - { - aVertexPosition:0, - aTextureCoord:0 - } - ); -} - -StripShader.prototype = Object.create(core.Shader.prototype); -StripShader.prototype.constructor = StripShader; -module.exports = StripShader; - -core.ShaderManager.registerPlugin('meshShader', StripShader); diff --git a/src/index.js b/src/index.js index 2c1f999..da8c001 100644 --- a/src/index.js +++ b/src/index.js @@ -1,6 +1,7 @@ var core = require('./core'); extendCore(require('./extras')); +extendCore(require('./mesh')); extendCore(require('./filters')); extendCore(require('./interaction')); extendCore(require('./loaders')); diff --git a/src/extras/index.js b/src/extras/index.js index 267e97c..6f14e0d 100644 --- a/src/extras/index.js +++ b/src/extras/index.js @@ -11,7 +11,6 @@ module.exports = { MovieClip: require('./MovieClip'), TilingSprite: require('./TilingSprite'), - mesh: require('./mesh/index'), cacheAsBitmap: require('./cacheAsBitmap'), getChildByName: require('./getChildByName') }; diff --git a/src/extras/mesh/Mesh.js b/src/extras/mesh/Mesh.js deleted file mode 100644 index 30431ae..0000000 --- a/src/extras/mesh/Mesh.js +++ /dev/null @@ -1,387 +0,0 @@ -var core = require('../../core'); - -/** - * Base mesh class - * @class - * @extends Container - * @memberof PIXI.extras - * @param texture {Texture} The texture to use - * @param [vertices] {Float32Arrif you want to specify the vertices - * @param [uvs] {Float32Array} if you want to specify the uvs - * @param [indices] {Uint16Array} if you want to specify the indices - * @param [drawMode] {number} the drawMode, can be any of the Mesh.DRAW_MODES consts - */ -function Mesh(texture, vertices, uvs, indices, drawMode) -{ - core.Container.call(this); - - /** - * The texture of the Mesh - * - * @member {Texture} - */ - this.texture = texture; - - /** - * The Uvs of the Mesh - * - * @member {Float32Array} - */ - this.uvs = uvs || new Float32Array([0, 1, - 1, 1, - 1, 0, - 0, 1]); - - /** - * An array of vertices - * - * @member {Float32Array} - */ - this.vertices = vertices || new Float32Array([0, 0, - 100, 0, - 100, 100, - 0, 100]); - - /* - * @member {Uint16Array} An array containing the indices of the vertices - */ - // TODO auto generate this based on draw mode! - this.indices = indices || new Uint16Array([0, 1, 2, 3]); - - /** - * Whether the Mesh is dirty or not - * - * @member {boolean} - */ - this.dirty = true; - - /** - * The blend mode to be applied to the sprite. Set to blendModes.NORMAL to remove any blend mode. - * - * @member {number} - * @default CONST.BLEND_MODES.NORMAL; - */ - this.blendMode = core.CONST.BLEND_MODES.NORMAL; - - /** - * Triangles in canvas mode are automatically antialiased, use this value to force triangles to overlap a bit with each other. - * - * @member {number}= - */ - this.canvasPadding = 0; - - /** - * The way the Mesh should be drawn, can be any of the Mesh.DRAW_MODES consts - * - * @member {number} - */ - this.drawMode = drawMode || Mesh.DRAW_MODES.TRIANGLE_MESH; -} - -// constructor -Mesh.prototype = Object.create(core.Container.prototype); -Mesh.prototype.constructor = Mesh; -module.exports = Mesh; - -/** - * Renders the object using the WebGL renderer - * - * @param renderer {WebGLRenderer} a reference to the WebGL renderer - */ -Mesh.prototype._renderWebGL = function (renderer) -{ - renderer.setObjectRenderer(renderer.plugins.mesh); - renderer.plugins.mesh.render(this); -}; - -/** - * Renders the object using the Canvas renderer - * - * @param renderer {CanvasRenderer} - */ -Mesh.prototype._renderCanvas = function (renderer) -{ - var context = renderer.context; - - var transform = this.worldTransform; - - if (renderer.roundPixels) - { - context.setTransform(transform.a, transform.b, transform.c, transform.d, transform.tx | 0, transform.ty | 0); - } - else - { - context.setTransform(transform.a, transform.b, transform.c, transform.d, transform.tx, transform.ty); - } - - if (this.drawMode === Mesh.DRAW_MODES.TRIANGLE_MESH) - { - this._renderCanvasTriangleMesh(context); - } - else - { - this._renderCanvasTriangles(context); - } -}; - -/** - * Draws the object in Triangle Mesh mode using canvas - * - * @param context {CanvasRenderingContext2D} the current drawing context - * @private - */ -Mesh.prototype._renderCanvasTriangleMesh = function (context) -{ - // draw triangles!! - var vertices = this.vertices; - var uvs = this.uvs; - - var length = vertices.length / 2; - // this.count++; - - for (var i = 0; i < length - 2; i++) - { - // draw some triangles! - var index = i * 2; - this._renderCanvasDrawTriangle(context, vertices, uvs, index, (index + 2), (index + 4)); - } -}; - -/** - * Draws the object in triangle mode using canvas - * - * @param context {CanvasRenderingContext2D} the current drawing context - * @private - */ -Mesh.prototype._renderCanvasTriangles = function (context) -{ - // draw triangles!! - var vertices = this.vertices; - var uvs = this.uvs; - var indices = this.indices; - - var length = indices.length; - // this.count++; - - for (var i = 0; i < length; i += 3) - { - // draw some triangles! - var index0 = indices[i] * 2, index1 = indices[i + 1] * 2, index2 = indices[i + 2] * 2; - this._renderCanvasDrawTriangle(context, vertices, uvs, index0, index1, index2); - } -}; - -/** - * Draws one of the triangles that form this Mesh - * - * @param context {CanvasRenderingContext2D} the current drawing context - * @param vertices {Float32Array} a reference to the vertices of the Mesh - * @param uvs {Float32Array} a reference to the uvs of the Mesh - * @param index0 {number} the index of the first vertex - * @param index1 {number} the index of the second vertex - * @param index2 {number} the index of the third vertex - * @private - */ -Mesh.prototype._renderCanvasDrawTriangle = function (context, vertices, uvs, index0, index1, index2) -{ - var textureSource = this.texture.baseTexture.source; - var textureWidth = this.texture.width; - var textureHeight = this.texture.height; - - var x0 = vertices[index0], x1 = vertices[index1], x2 = vertices[index2]; - var y0 = vertices[index0 + 1], y1 = vertices[index1 + 1], y2 = vertices[index2 + 1]; - - var u0 = uvs[index0] * textureWidth, u1 = uvs[index1] * textureWidth, u2 = uvs[index2] * textureWidth; - var v0 = uvs[index0 + 1] * textureHeight, v1 = uvs[index1 + 1] * textureHeight, v2 = uvs[index2 + 1] * textureHeight; - - if (this.canvasPadding > 0) - { - var paddingX = this.canvasPadding / this.worldTransform.a; - var paddingY = this.canvasPadding / this.worldTransform.d; - var centerX = (x0 + x1 + x2) / 3; - var centerY = (y0 + y1 + y2) / 3; - - var normX = x0 - centerX; - var normY = y0 - centerY; - - var dist = Math.sqrt(normX * normX + normY * normY); - x0 = centerX + (normX / dist) * (dist + paddingX); - y0 = centerY + (normY / dist) * (dist + paddingY); - - // - - normX = x1 - centerX; - normY = y1 - centerY; - - dist = Math.sqrt(normX * normX + normY * normY); - x1 = centerX + (normX / dist) * (dist + paddingX); - y1 = centerY + (normY / dist) * (dist + paddingY); - - normX = x2 - centerX; - normY = y2 - centerY; - - dist = Math.sqrt(normX * normX + normY * normY); - x2 = centerX + (normX / dist) * (dist + paddingX); - y2 = centerY + (normY / dist) * (dist + paddingY); - } - - context.save(); - context.beginPath(); - - - context.moveTo(x0, y0); - context.lineTo(x1, y1); - context.lineTo(x2, y2); - - context.closePath(); - - context.clip(); - - // Compute matrix transform - var delta = (u0 * v1) + (v0 * u2) + (u1 * v2) - (v1 * u2) - (v0 * u1) - (u0 * v2); - var deltaA = (x0 * v1) + (v0 * x2) + (x1 * v2) - (v1 * x2) - (v0 * x1) - (x0 * v2); - var deltaB = (u0 * x1) + (x0 * u2) + (u1 * x2) - (x1 * u2) - (x0 * u1) - (u0 * x2); - var deltaC = (u0 * v1 * x2) + (v0 * x1 * u2) + (x0 * u1 * v2) - (x0 * v1 * u2) - (v0 * u1 * x2) - (u0 * x1 * v2); - var deltaD = (y0 * v1) + (v0 * y2) + (y1 * v2) - (v1 * y2) - (v0 * y1) - (y0 * v2); - var deltaE = (u0 * y1) + (y0 * u2) + (u1 * y2) - (y1 * u2) - (y0 * u1) - (u0 * y2); - var deltaF = (u0 * v1 * y2) + (v0 * y1 * u2) + (y0 * u1 * v2) - (y0 * v1 * u2) - (v0 * u1 * y2) - (u0 * y1 * v2); - - context.transform(deltaA / delta, deltaD / delta, - deltaB / delta, deltaE / delta, - deltaC / delta, deltaF / delta); - - context.drawImage(textureSource, 0, 0); - context.restore(); -}; - - - -/** - * Renders a flat Mesh - * - * @param Mesh {Mesh} The Mesh to render - * @private - */ -Mesh.prototype.renderMeshFlat = function (Mesh) -{ - var context = this.context; - var vertices = Mesh.vertices; - - var length = vertices.length/2; - // this.count++; - - context.beginPath(); - for (var i=1; i < length-2; i++) - { - // draw some triangles! - var index = i*2; - - var x0 = vertices[index], x1 = vertices[index+2], x2 = vertices[index+4]; - var y0 = vertices[index+1], y1 = vertices[index+3], y2 = vertices[index+5]; - - context.moveTo(x0, y0); - context.lineTo(x1, y1); - context.lineTo(x2, y2); - } - - context.fillStyle = '#FF0000'; - context.fill(); - context.closePath(); -}; - -/* -Mesh.prototype.setTexture = function (texture) -{ - //TODO SET THE TEXTURES - //TODO VISIBILITY - //TODO SETTER - - // stop current texture - this.texture = texture; - this.width = texture.frame.width; - this.height = texture.frame.height; - this.updateFrame = true; -}; - */ - -/** - * When the texture is updated, this event will fire to update the scale and frame - * - * @param event - * @private - */ - -Mesh.prototype.onTextureUpdate = function () -{ - this.updateFrame = true; -}; - -/** - * Returns the bounds of the mesh as a rectangle. The bounds calculation takes the worldTransform into account. - * - * @param matrix {Matrix} the transformation matrix of the sprite - * @return {Rectangle} the framing rectangle - */ -Mesh.prototype.getBounds = function (matrix) -{ - var worldTransform = matrix || this.worldTransform; - - var a = worldTransform.a; - var b = worldTransform.b; - var c = worldTransform.c; - var d = worldTransform.d; - var tx = worldTransform.tx; - var ty = worldTransform.ty; - - var maxX = -Infinity; - var maxY = -Infinity; - - var minX = Infinity; - var minY = Infinity; - - var vertices = this.vertices; - for (var i = 0, n = vertices.length; i < n; i += 2) - { - var rawX = vertices[i], rawY = vertices[i + 1]; - var x = (a * rawX) + (c * rawY) + tx; - var y = (d * rawY) + (b * rawX) + ty; - - minX = x < minX ? x : minX; - minY = y < minY ? y : minY; - - maxX = x > maxX ? x : maxX; - maxY = y > maxY ? y : maxY; - } - - if (minX === -Infinity || maxY === Infinity) - { - return core.math.Rectangle.EMPTY; - } - - var bounds = this._bounds; - - bounds.x = minX; - bounds.width = maxX - minX; - - bounds.y = minY; - bounds.height = maxY - minY; - - // store a reference so that if this function gets called again in the render cycle we do not have to recalculate - this._currentBounds = bounds; - - return bounds; -}; - -/** - * Different drawing buffer modes supported - * - * @static - * @constant - * @property {object} DRAW_MODES - * @property {number} DRAW_MODES.TRIANGLE_MESH - * @property {number} DRAW_MODES.TRIANGLES - */ -Mesh.DRAW_MODES = { - TRIANGLE_MESH: 0, - TRIANGLES: 1 -}; diff --git a/src/extras/mesh/Rope.js b/src/extras/mesh/Rope.js deleted file mode 100644 index 8119995..0000000 --- a/src/extras/mesh/Rope.js +++ /dev/null @@ -1,192 +0,0 @@ -var Mesh = require('./Mesh'); - -/** - * The rope allows you to draw a texture across several points and them manipulate these points - * - *```js - * for (var i = 0; i < 20; i++) { - * points.push(new PIXI.Point(i * 50, 0)); - * }; - * var rope = new PIXI.Rope(PIXI.Texture.fromImage("snake.png"), points); - * ``` - * - * @class - * @extends Mesh - * @memberof PIXI.extras - * @param {Texture} texture - The texture to use on the rope. - * @param {Array} points - An array of {Point} objects to construct this rope. - * - */ -function Rope(texture, points) -{ - Mesh.call(this, texture); - - /* - * @member {Array} An array of points that determine the rope - */ - this.points = points; - - /* - * @member {Float32Array} An array of vertices used to construct this rope. - */ - this.vertices = new Float32Array(points.length * 4); - - /* - * @member {Float32Array} The WebGL Uvs of the rope. - */ - this.uvs = new Float32Array(points.length * 4); - - /* - * @member {Float32Array} An array containing the color components - */ - this.colors = new Float32Array(points.length * 2); - - /* - * @member {Uint16Array} An array containing the indices of the vertices - */ - this.indices = new Uint16Array(points.length * 2); - - this.refresh(); -} - - -// constructor -Rope.prototype = Object.create(Mesh.prototype); -Rope.prototype.constructor = Rope; -module.exports = Rope; - -/** - * Refreshes - * - */ -Rope.prototype.refresh = function () -{ - var points = this.points; - - if (points.length < 1) - { - return; - } - - var uvs = this.uvs; - - var indices = this.indices; - var colors = this.colors; - - // this.count -= 0.2; - - uvs[0] = 0; - uvs[1] = 0; - uvs[2] = 0; - uvs[3] = 1; - - colors[0] = 1; - colors[1] = 1; - - indices[0] = 0; - indices[1] = 1; - - var total = points.length, - point, index, amount; - - for (var i = 1; i < total; i++) - { - point = points[i]; - index = i * 4; - // time to do some smart drawing! - amount = i / (total-1); - - if (i%2) - { - uvs[index] = amount; - uvs[index+1] = 0; - - uvs[index+2] = amount; - uvs[index+3] = 1; - } - else - { - uvs[index] = amount; - uvs[index+1] = 0; - - uvs[index+2] = amount; - uvs[index+3] = 1; - } - - index = i * 2; - colors[index] = 1; - colors[index+1] = 1; - - index = i * 2; - indices[index] = index; - indices[index + 1] = index + 1; - } -}; - -/* - * Updates the object transform for rendering - * - * @private - */ -Rope.prototype.updateTransform = function () -{ - var points = this.points; - - if (points.length < 1) - { - return; - } - - var lastPoint = points[0]; - var nextPoint; - var perpX = 0; - var perpY = 0; - - // this.count -= 0.2; - - var vertices = this.vertices; - var total = points.length, - point, index, ratio, perpLength, num; - - for (var i = 0; i < total; i++) - { - point = points[i]; - index = i * 4; - - if (i < points.length-1) - { - nextPoint = points[i+1]; - } - else - { - nextPoint = point; - } - - perpY = -(nextPoint.x - lastPoint.x); - perpX = nextPoint.y - lastPoint.y; - - ratio = (1 - (i / (total-1))) * 10; - - if (ratio > 1) - { - ratio = 1; - } - - perpLength = Math.sqrt(perpX * perpX + perpY * perpY); - num = this.texture.height / 2; //(20 + Math.abs(Math.sin((i + this.count) * 0.3) * 50) )* ratio; - perpX /= perpLength; - perpY /= perpLength; - - perpX *= num; - perpY *= num; - - vertices[index] = point.x + perpX; - vertices[index+1] = point.y + perpY; - vertices[index+2] = point.x - perpX; - vertices[index+3] = point.y - perpY; - - lastPoint = point; - } - - this.containerUpdateTransform(); -}; diff --git a/src/extras/mesh/index.js b/src/extras/mesh/index.js deleted file mode 100644 index dd37f87..0000000 --- a/src/extras/mesh/index.js +++ /dev/null @@ -1,16 +0,0 @@ -/** - * @file Main export of the PIXI extras library - * @author Mat Groves - * @copyright 2013-2015 GoodBoyDigital - * @license {@link https://github.com/GoodBoyDigital/pixi.js/blob/master/LICENSE|MIT License} - */ - -/** - * @namespace PIXI.extras - */ -module.exports = { - Mesh: require('./Mesh'), - Rope: require('./Rope'), - MeshRenderer: require('./webgl/MeshRenderer'), - MeshShader: require('./webgl/MeshShader') -}; diff --git a/src/extras/mesh/webgl/MeshRenderer.js b/src/extras/mesh/webgl/MeshRenderer.js deleted file mode 100644 index 2dd7678..0000000 --- a/src/extras/mesh/webgl/MeshRenderer.js +++ /dev/null @@ -1,215 +0,0 @@ -var ObjectRenderer = require('../../../core/renderers/webgl/utils/ObjectRenderer'), - WebGLRenderer = require('../../../core/renderers/webgl/WebGLRenderer'); - -/** - * @author Mat Groves - * - * Big thanks to the very clever Matt DesLauriers https://github.com/mattdesl/ - * for creating the original pixi version! - * Also a thanks to https://github.com/bchevalier for tweaking the tint and alpha so that they now share 4 bytes on the vertex buffer - * - * Heavily inspired by LibGDX's MeshRenderer: - * https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/graphics/g2d/MeshRenderer.java - */ - -/** - * - * @class - * @private - * @memberof PIXI - * @extends ObjectRenderer - * @param renderer {WebGLRenderer} The renderer this sprite batch works for. - */ -function MeshRenderer(renderer) -{ - ObjectRenderer.call(this, renderer); - - - /** - * Holds the indices - * - * @member {Uint16Array} - */ - this.indices = new Uint16Array(15000); - - //TODO this could be a single buffer shared amongst all renderers as we reuse this set up in most renderers - for (var i=0, j=0; i < 15000; i += 6, j += 4) - { - this.indices[i + 0] = j + 0; - this.indices[i + 1] = j + 1; - this.indices[i + 2] = j + 2; - this.indices[i + 3] = j + 0; - this.indices[i + 4] = j + 2; - this.indices[i + 5] = j + 3; - } -} - -MeshRenderer.prototype = Object.create(ObjectRenderer.prototype); -MeshRenderer.prototype.constructor = MeshRenderer; -module.exports = MeshRenderer; - -WebGLRenderer.registerPlugin('mesh', MeshRenderer); - -/** - * Sets up the renderer context and necessary buffers. - * - * @private - * @param gl {WebGLRenderingContext} the current WebGL drawing context - */ -MeshRenderer.prototype.onContextChange = function () -{ - -}; - -/** - * Renders the sprite object. - * - * @param mesh {Mesh} the mesh to render - */ -MeshRenderer.prototype.render = function (mesh) -{ -// return; - if(!mesh._vertexBuffer) - { - this._initWebGL(mesh); - } - - var renderer = this.renderer, - gl = renderer.gl, - texture = mesh.texture.baseTexture, - shader = renderer.shaderManager.plugins.meshShader; - -// var drawMode = mesh.drawMode === Strip.DRAW_MODES.TRIANGLE_STRIP ? gl.TRIANGLE_STRIP : gl.TRIANGLES; - var drawMode = gl.TRIANGLE_STRIP; - - renderer.blendModeManager.setBlendMode(mesh.blendMode); - - - // set uniforms - gl.uniformMatrix3fv(shader.uniforms.translationMatrix._location, false, mesh.worldTransform.toArray(true)); - - gl.uniformMatrix3fv(shader.uniforms.projectionMatrix._location, false, renderer.currentRenderTarget.projectionMatrix.toArray(true)); - gl.uniform1f(shader.uniforms.alpha._location, mesh.worldAlpha); - - if (!mesh.dirty) - { - - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._vertexBuffer); - gl.bufferSubData(gl.ARRAY_BUFFER, 0, mesh.vertices); - gl.vertexAttribPointer(shader.attributes.aVertexPosition, 2, gl.FLOAT, false, 0, 0); - - - // update the uvs - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._uvBuffer); - gl.vertexAttribPointer(shader.attributes.aTextureCoord, 2, gl.FLOAT, false, 0, 0); - - - gl.activeTexture(gl.TEXTURE0); - - if (!texture._glTextures[gl.id]) - { - this.renderer.updateTexture(texture); - } - else - { - // bind the current texture - gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]); - } - } - else - { - - mesh.dirty = false; - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER, mesh.vertices, gl.STATIC_DRAW); - gl.vertexAttribPointer(shader.attributes.aVertexPosition, 2, gl.FLOAT, false, 0, 0); - - // update the uvs - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._uvBuffer); - gl.bufferData(gl.ARRAY_BUFFER, mesh.uvs, gl.STATIC_DRAW); - gl.vertexAttribPointer(shader.attributes.aTextureCoord, 2, gl.FLOAT, false, 0, 0); - - gl.activeTexture(gl.TEXTURE0); - - if (!texture._glTextures[gl.id]) - { - this.renderer.updateTexture(texture); - } - else - { - // bind the current texture - gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]); - } - - // dont need to upload! - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, mesh._indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, mesh.indices, gl.STATIC_DRAW); - - } - - gl.drawElements(drawMode, mesh.indices.length, gl.UNSIGNED_SHORT, 0); - -}; - -/** - * Prepares all the buffers to render this mesh - * @param mesh {Mesh} the mesh to render - */ -MeshRenderer.prototype._initWebGL = function (mesh) -{ - // build the strip! - var gl = this.renderer.gl; - - mesh._vertexBuffer = gl.createBuffer(); - mesh._indexBuffer = gl.createBuffer(); - mesh._uvBuffer = gl.createBuffer(); - mesh._colorBuffer = gl.createBuffer(); - - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER, mesh.vertices, gl.DYNAMIC_DRAW); - - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._uvBuffer); - gl.bufferData(gl.ARRAY_BUFFER, mesh.uvs, gl.STATIC_DRAW); - - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._colorBuffer); - gl.bufferData(gl.ARRAY_BUFFER, mesh.colors, gl.STATIC_DRAW); - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, mesh._indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, mesh.indices, gl.STATIC_DRAW); -}; - - -/** - * Empties the current batch. - * - */ -MeshRenderer.prototype.flush = function () -{ - -}; - -/** - * Starts a new mesh renderer. - * - */ -MeshRenderer.prototype.start = function () -{ - var gl = this.renderer.gl, - shader = this.renderer.shaderManager.plugins.meshShader; - - this.renderer.shaderManager.setShader(shader); - - // dont need to upload! - //gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indices); - - - // this.s -}; - -/** - * Destroys the Mesh renderer - * - */ -MeshRenderer.prototype.destroy = function () -{ -}; diff --git a/src/extras/mesh/webgl/MeshShader.js b/src/extras/mesh/webgl/MeshShader.js deleted file mode 100644 index 51c03f5..0000000 --- a/src/extras/mesh/webgl/MeshShader.js +++ /dev/null @@ -1,59 +0,0 @@ -var core = require('../../../core'); - -/** - * @class - * @extends Shader - * @memberof PIXI.extras - * @param shaderManager {ShaderManager} The WebGL shader manager this shader works for. - */ -function StripShader(shaderManager) -{ - core.Shader.call(this, - shaderManager, - // vertex shader - [ - 'precision lowp float;', - 'attribute vec2 aVertexPosition;', - 'attribute vec2 aTextureCoord;', - - 'uniform mat3 translationMatrix;', - 'uniform mat3 projectionMatrix;', - - 'varying vec2 vTextureCoord;', - - 'void main(void){', - ' gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);', - ' vTextureCoord = aTextureCoord;', - '}' - ].join('\n'), - [ - 'precision lowp float;', - - 'varying vec2 vTextureCoord;', - 'uniform float alpha;', - - 'uniform sampler2D uSampler;', - - 'void main(void){', - ' gl_FragColor = texture2D(uSampler, vTextureCoord) * alpha ;', - '}' - ].join('\n'), - // custom uniforms - { - alpha: { type: '1f', value: 0 }, - translationMatrix: { type: 'mat3', value: new Float32Array(9) }, - projectionMatrix: { type: 'mat3', value: new Float32Array(9) } - }, - // custom attributes - { - aVertexPosition:0, - aTextureCoord:0 - } - ); -} - -StripShader.prototype = Object.create(core.Shader.prototype); -StripShader.prototype.constructor = StripShader; -module.exports = StripShader; - -core.ShaderManager.registerPlugin('meshShader', StripShader); diff --git a/src/index.js b/src/index.js index 2c1f999..da8c001 100644 --- a/src/index.js +++ b/src/index.js @@ -1,6 +1,7 @@ var core = require('./core'); extendCore(require('./extras')); +extendCore(require('./mesh')); extendCore(require('./filters')); extendCore(require('./interaction')); extendCore(require('./loaders')); diff --git a/src/mesh/Mesh.js b/src/mesh/Mesh.js new file mode 100644 index 0000000..c006078 --- /dev/null +++ b/src/mesh/Mesh.js @@ -0,0 +1,387 @@ +var core = require('../core'); + +/** + * Base mesh class + * @class + * @extends Container + * @memberof PIXI.extras + * @param texture {Texture} The texture to use + * @param [vertices] {Float32Arrif you want to specify the vertices + * @param [uvs] {Float32Array} if you want to specify the uvs + * @param [indices] {Uint16Array} if you want to specify the indices + * @param [drawMode] {number} the drawMode, can be any of the Mesh.DRAW_MODES consts + */ +function Mesh(texture, vertices, uvs, indices, drawMode) +{ + core.Container.call(this); + + /** + * The texture of the Mesh + * + * @member {Texture} + */ + this.texture = texture; + + /** + * The Uvs of the Mesh + * + * @member {Float32Array} + */ + this.uvs = uvs || new Float32Array([0, 1, + 1, 1, + 1, 0, + 0, 1]); + + /** + * An array of vertices + * + * @member {Float32Array} + */ + this.vertices = vertices || new Float32Array([0, 0, + 100, 0, + 100, 100, + 0, 100]); + + /* + * @member {Uint16Array} An array containing the indices of the vertices + */ + // TODO auto generate this based on draw mode! + this.indices = indices || new Uint16Array([0, 1, 2, 3]); + + /** + * Whether the Mesh is dirty or not + * + * @member {boolean} + */ + this.dirty = true; + + /** + * The blend mode to be applied to the sprite. Set to blendModes.NORMAL to remove any blend mode. + * + * @member {number} + * @default CONST.BLEND_MODES.NORMAL; + */ + this.blendMode = core.CONST.BLEND_MODES.NORMAL; + + /** + * Triangles in canvas mode are automatically antialiased, use this value to force triangles to overlap a bit with each other. + * + * @member {number}= + */ + this.canvasPadding = 0; + + /** + * The way the Mesh should be drawn, can be any of the Mesh.DRAW_MODES consts + * + * @member {number} + */ + this.drawMode = drawMode || Mesh.DRAW_MODES.TRIANGLE_MESH; +} + +// constructor +Mesh.prototype = Object.create(core.Container.prototype); +Mesh.prototype.constructor = Mesh; +module.exports = Mesh; + +/** + * Renders the object using the WebGL renderer + * + * @param renderer {WebGLRenderer} a reference to the WebGL renderer + */ +Mesh.prototype._renderWebGL = function (renderer) +{ + renderer.setObjectRenderer(renderer.plugins.mesh); + renderer.plugins.mesh.render(this); +}; + +/** + * Renders the object using the Canvas renderer + * + * @param renderer {CanvasRenderer} + */ +Mesh.prototype._renderCanvas = function (renderer) +{ + var context = renderer.context; + + var transform = this.worldTransform; + + if (renderer.roundPixels) + { + context.setTransform(transform.a, transform.b, transform.c, transform.d, transform.tx | 0, transform.ty | 0); + } + else + { + context.setTransform(transform.a, transform.b, transform.c, transform.d, transform.tx, transform.ty); + } + + if (this.drawMode === Mesh.DRAW_MODES.TRIANGLE_MESH) + { + this._renderCanvasTriangleMesh(context); + } + else + { + this._renderCanvasTriangles(context); + } +}; + +/** + * Draws the object in Triangle Mesh mode using canvas + * + * @param context {CanvasRenderingContext2D} the current drawing context + * @private + */ +Mesh.prototype._renderCanvasTriangleMesh = function (context) +{ + // draw triangles!! + var vertices = this.vertices; + var uvs = this.uvs; + + var length = vertices.length / 2; + // this.count++; + + for (var i = 0; i < length - 2; i++) + { + // draw some triangles! + var index = i * 2; + this._renderCanvasDrawTriangle(context, vertices, uvs, index, (index + 2), (index + 4)); + } +}; + +/** + * Draws the object in triangle mode using canvas + * + * @param context {CanvasRenderingContext2D} the current drawing context + * @private + */ +Mesh.prototype._renderCanvasTriangles = function (context) +{ + // draw triangles!! + var vertices = this.vertices; + var uvs = this.uvs; + var indices = this.indices; + + var length = indices.length; + // this.count++; + + for (var i = 0; i < length; i += 3) + { + // draw some triangles! + var index0 = indices[i] * 2, index1 = indices[i + 1] * 2, index2 = indices[i + 2] * 2; + this._renderCanvasDrawTriangle(context, vertices, uvs, index0, index1, index2); + } +}; + +/** + * Draws one of the triangles that form this Mesh + * + * @param context {CanvasRenderingContext2D} the current drawing context + * @param vertices {Float32Array} a reference to the vertices of the Mesh + * @param uvs {Float32Array} a reference to the uvs of the Mesh + * @param index0 {number} the index of the first vertex + * @param index1 {number} the index of the second vertex + * @param index2 {number} the index of the third vertex + * @private + */ +Mesh.prototype._renderCanvasDrawTriangle = function (context, vertices, uvs, index0, index1, index2) +{ + var textureSource = this.texture.baseTexture.source; + var textureWidth = this.texture.width; + var textureHeight = this.texture.height; + + var x0 = vertices[index0], x1 = vertices[index1], x2 = vertices[index2]; + var y0 = vertices[index0 + 1], y1 = vertices[index1 + 1], y2 = vertices[index2 + 1]; + + var u0 = uvs[index0] * textureWidth, u1 = uvs[index1] * textureWidth, u2 = uvs[index2] * textureWidth; + var v0 = uvs[index0 + 1] * textureHeight, v1 = uvs[index1 + 1] * textureHeight, v2 = uvs[index2 + 1] * textureHeight; + + if (this.canvasPadding > 0) + { + var paddingX = this.canvasPadding / this.worldTransform.a; + var paddingY = this.canvasPadding / this.worldTransform.d; + var centerX = (x0 + x1 + x2) / 3; + var centerY = (y0 + y1 + y2) / 3; + + var normX = x0 - centerX; + var normY = y0 - centerY; + + var dist = Math.sqrt(normX * normX + normY * normY); + x0 = centerX + (normX / dist) * (dist + paddingX); + y0 = centerY + (normY / dist) * (dist + paddingY); + + // + + normX = x1 - centerX; + normY = y1 - centerY; + + dist = Math.sqrt(normX * normX + normY * normY); + x1 = centerX + (normX / dist) * (dist + paddingX); + y1 = centerY + (normY / dist) * (dist + paddingY); + + normX = x2 - centerX; + normY = y2 - centerY; + + dist = Math.sqrt(normX * normX + normY * normY); + x2 = centerX + (normX / dist) * (dist + paddingX); + y2 = centerY + (normY / dist) * (dist + paddingY); + } + + context.save(); + context.beginPath(); + + + context.moveTo(x0, y0); + context.lineTo(x1, y1); + context.lineTo(x2, y2); + + context.closePath(); + + context.clip(); + + // Compute matrix transform + var delta = (u0 * v1) + (v0 * u2) + (u1 * v2) - (v1 * u2) - (v0 * u1) - (u0 * v2); + var deltaA = (x0 * v1) + (v0 * x2) + (x1 * v2) - (v1 * x2) - (v0 * x1) - (x0 * v2); + var deltaB = (u0 * x1) + (x0 * u2) + (u1 * x2) - (x1 * u2) - (x0 * u1) - (u0 * x2); + var deltaC = (u0 * v1 * x2) + (v0 * x1 * u2) + (x0 * u1 * v2) - (x0 * v1 * u2) - (v0 * u1 * x2) - (u0 * x1 * v2); + var deltaD = (y0 * v1) + (v0 * y2) + (y1 * v2) - (v1 * y2) - (v0 * y1) - (y0 * v2); + var deltaE = (u0 * y1) + (y0 * u2) + (u1 * y2) - (y1 * u2) - (y0 * u1) - (u0 * y2); + var deltaF = (u0 * v1 * y2) + (v0 * y1 * u2) + (y0 * u1 * v2) - (y0 * v1 * u2) - (v0 * u1 * y2) - (u0 * y1 * v2); + + context.transform(deltaA / delta, deltaD / delta, + deltaB / delta, deltaE / delta, + deltaC / delta, deltaF / delta); + + context.drawImage(textureSource, 0, 0); + context.restore(); +}; + + + +/** + * Renders a flat Mesh + * + * @param Mesh {Mesh} The Mesh to render + * @private + */ +Mesh.prototype.renderMeshFlat = function (Mesh) +{ + var context = this.context; + var vertices = Mesh.vertices; + + var length = vertices.length/2; + // this.count++; + + context.beginPath(); + for (var i=1; i < length-2; i++) + { + // draw some triangles! + var index = i*2; + + var x0 = vertices[index], x1 = vertices[index+2], x2 = vertices[index+4]; + var y0 = vertices[index+1], y1 = vertices[index+3], y2 = vertices[index+5]; + + context.moveTo(x0, y0); + context.lineTo(x1, y1); + context.lineTo(x2, y2); + } + + context.fillStyle = '#FF0000'; + context.fill(); + context.closePath(); +}; + +/* +Mesh.prototype.setTexture = function (texture) +{ + //TODO SET THE TEXTURES + //TODO VISIBILITY + //TODO SETTER + + // stop current texture + this.texture = texture; + this.width = texture.frame.width; + this.height = texture.frame.height; + this.updateFrame = true; +}; + */ + +/** + * When the texture is updated, this event will fire to update the scale and frame + * + * @param event + * @private + */ + +Mesh.prototype.onTextureUpdate = function () +{ + this.updateFrame = true; +}; + +/** + * Returns the bounds of the mesh as a rectangle. The bounds calculation takes the worldTransform into account. + * + * @param matrix {Matrix} the transformation matrix of the sprite + * @return {Rectangle} the framing rectangle + */ +Mesh.prototype.getBounds = function (matrix) +{ + var worldTransform = matrix || this.worldTransform; + + var a = worldTransform.a; + var b = worldTransform.b; + var c = worldTransform.c; + var d = worldTransform.d; + var tx = worldTransform.tx; + var ty = worldTransform.ty; + + var maxX = -Infinity; + var maxY = -Infinity; + + var minX = Infinity; + var minY = Infinity; + + var vertices = this.vertices; + for (var i = 0, n = vertices.length; i < n; i += 2) + { + var rawX = vertices[i], rawY = vertices[i + 1]; + var x = (a * rawX) + (c * rawY) + tx; + var y = (d * rawY) + (b * rawX) + ty; + + minX = x < minX ? x : minX; + minY = y < minY ? y : minY; + + maxX = x > maxX ? x : maxX; + maxY = y > maxY ? y : maxY; + } + + if (minX === -Infinity || maxY === Infinity) + { + return core.math.Rectangle.EMPTY; + } + + var bounds = this._bounds; + + bounds.x = minX; + bounds.width = maxX - minX; + + bounds.y = minY; + bounds.height = maxY - minY; + + // store a reference so that if this function gets called again in the render cycle we do not have to recalculate + this._currentBounds = bounds; + + return bounds; +}; + +/** + * Different drawing buffer modes supported + * + * @static + * @constant + * @property {object} DRAW_MODES + * @property {number} DRAW_MODES.TRIANGLE_MESH + * @property {number} DRAW_MODES.TRIANGLES + */ +Mesh.DRAW_MODES = { + TRIANGLE_MESH: 0, + TRIANGLES: 1 +}; diff --git a/src/extras/index.js b/src/extras/index.js index 267e97c..6f14e0d 100644 --- a/src/extras/index.js +++ b/src/extras/index.js @@ -11,7 +11,6 @@ module.exports = { MovieClip: require('./MovieClip'), TilingSprite: require('./TilingSprite'), - mesh: require('./mesh/index'), cacheAsBitmap: require('./cacheAsBitmap'), getChildByName: require('./getChildByName') }; diff --git a/src/extras/mesh/Mesh.js b/src/extras/mesh/Mesh.js deleted file mode 100644 index 30431ae..0000000 --- a/src/extras/mesh/Mesh.js +++ /dev/null @@ -1,387 +0,0 @@ -var core = require('../../core'); - -/** - * Base mesh class - * @class - * @extends Container - * @memberof PIXI.extras - * @param texture {Texture} The texture to use - * @param [vertices] {Float32Arrif you want to specify the vertices - * @param [uvs] {Float32Array} if you want to specify the uvs - * @param [indices] {Uint16Array} if you want to specify the indices - * @param [drawMode] {number} the drawMode, can be any of the Mesh.DRAW_MODES consts - */ -function Mesh(texture, vertices, uvs, indices, drawMode) -{ - core.Container.call(this); - - /** - * The texture of the Mesh - * - * @member {Texture} - */ - this.texture = texture; - - /** - * The Uvs of the Mesh - * - * @member {Float32Array} - */ - this.uvs = uvs || new Float32Array([0, 1, - 1, 1, - 1, 0, - 0, 1]); - - /** - * An array of vertices - * - * @member {Float32Array} - */ - this.vertices = vertices || new Float32Array([0, 0, - 100, 0, - 100, 100, - 0, 100]); - - /* - * @member {Uint16Array} An array containing the indices of the vertices - */ - // TODO auto generate this based on draw mode! - this.indices = indices || new Uint16Array([0, 1, 2, 3]); - - /** - * Whether the Mesh is dirty or not - * - * @member {boolean} - */ - this.dirty = true; - - /** - * The blend mode to be applied to the sprite. Set to blendModes.NORMAL to remove any blend mode. - * - * @member {number} - * @default CONST.BLEND_MODES.NORMAL; - */ - this.blendMode = core.CONST.BLEND_MODES.NORMAL; - - /** - * Triangles in canvas mode are automatically antialiased, use this value to force triangles to overlap a bit with each other. - * - * @member {number}= - */ - this.canvasPadding = 0; - - /** - * The way the Mesh should be drawn, can be any of the Mesh.DRAW_MODES consts - * - * @member {number} - */ - this.drawMode = drawMode || Mesh.DRAW_MODES.TRIANGLE_MESH; -} - -// constructor -Mesh.prototype = Object.create(core.Container.prototype); -Mesh.prototype.constructor = Mesh; -module.exports = Mesh; - -/** - * Renders the object using the WebGL renderer - * - * @param renderer {WebGLRenderer} a reference to the WebGL renderer - */ -Mesh.prototype._renderWebGL = function (renderer) -{ - renderer.setObjectRenderer(renderer.plugins.mesh); - renderer.plugins.mesh.render(this); -}; - -/** - * Renders the object using the Canvas renderer - * - * @param renderer {CanvasRenderer} - */ -Mesh.prototype._renderCanvas = function (renderer) -{ - var context = renderer.context; - - var transform = this.worldTransform; - - if (renderer.roundPixels) - { - context.setTransform(transform.a, transform.b, transform.c, transform.d, transform.tx | 0, transform.ty | 0); - } - else - { - context.setTransform(transform.a, transform.b, transform.c, transform.d, transform.tx, transform.ty); - } - - if (this.drawMode === Mesh.DRAW_MODES.TRIANGLE_MESH) - { - this._renderCanvasTriangleMesh(context); - } - else - { - this._renderCanvasTriangles(context); - } -}; - -/** - * Draws the object in Triangle Mesh mode using canvas - * - * @param context {CanvasRenderingContext2D} the current drawing context - * @private - */ -Mesh.prototype._renderCanvasTriangleMesh = function (context) -{ - // draw triangles!! - var vertices = this.vertices; - var uvs = this.uvs; - - var length = vertices.length / 2; - // this.count++; - - for (var i = 0; i < length - 2; i++) - { - // draw some triangles! - var index = i * 2; - this._renderCanvasDrawTriangle(context, vertices, uvs, index, (index + 2), (index + 4)); - } -}; - -/** - * Draws the object in triangle mode using canvas - * - * @param context {CanvasRenderingContext2D} the current drawing context - * @private - */ -Mesh.prototype._renderCanvasTriangles = function (context) -{ - // draw triangles!! - var vertices = this.vertices; - var uvs = this.uvs; - var indices = this.indices; - - var length = indices.length; - // this.count++; - - for (var i = 0; i < length; i += 3) - { - // draw some triangles! - var index0 = indices[i] * 2, index1 = indices[i + 1] * 2, index2 = indices[i + 2] * 2; - this._renderCanvasDrawTriangle(context, vertices, uvs, index0, index1, index2); - } -}; - -/** - * Draws one of the triangles that form this Mesh - * - * @param context {CanvasRenderingContext2D} the current drawing context - * @param vertices {Float32Array} a reference to the vertices of the Mesh - * @param uvs {Float32Array} a reference to the uvs of the Mesh - * @param index0 {number} the index of the first vertex - * @param index1 {number} the index of the second vertex - * @param index2 {number} the index of the third vertex - * @private - */ -Mesh.prototype._renderCanvasDrawTriangle = function (context, vertices, uvs, index0, index1, index2) -{ - var textureSource = this.texture.baseTexture.source; - var textureWidth = this.texture.width; - var textureHeight = this.texture.height; - - var x0 = vertices[index0], x1 = vertices[index1], x2 = vertices[index2]; - var y0 = vertices[index0 + 1], y1 = vertices[index1 + 1], y2 = vertices[index2 + 1]; - - var u0 = uvs[index0] * textureWidth, u1 = uvs[index1] * textureWidth, u2 = uvs[index2] * textureWidth; - var v0 = uvs[index0 + 1] * textureHeight, v1 = uvs[index1 + 1] * textureHeight, v2 = uvs[index2 + 1] * textureHeight; - - if (this.canvasPadding > 0) - { - var paddingX = this.canvasPadding / this.worldTransform.a; - var paddingY = this.canvasPadding / this.worldTransform.d; - var centerX = (x0 + x1 + x2) / 3; - var centerY = (y0 + y1 + y2) / 3; - - var normX = x0 - centerX; - var normY = y0 - centerY; - - var dist = Math.sqrt(normX * normX + normY * normY); - x0 = centerX + (normX / dist) * (dist + paddingX); - y0 = centerY + (normY / dist) * (dist + paddingY); - - // - - normX = x1 - centerX; - normY = y1 - centerY; - - dist = Math.sqrt(normX * normX + normY * normY); - x1 = centerX + (normX / dist) * (dist + paddingX); - y1 = centerY + (normY / dist) * (dist + paddingY); - - normX = x2 - centerX; - normY = y2 - centerY; - - dist = Math.sqrt(normX * normX + normY * normY); - x2 = centerX + (normX / dist) * (dist + paddingX); - y2 = centerY + (normY / dist) * (dist + paddingY); - } - - context.save(); - context.beginPath(); - - - context.moveTo(x0, y0); - context.lineTo(x1, y1); - context.lineTo(x2, y2); - - context.closePath(); - - context.clip(); - - // Compute matrix transform - var delta = (u0 * v1) + (v0 * u2) + (u1 * v2) - (v1 * u2) - (v0 * u1) - (u0 * v2); - var deltaA = (x0 * v1) + (v0 * x2) + (x1 * v2) - (v1 * x2) - (v0 * x1) - (x0 * v2); - var deltaB = (u0 * x1) + (x0 * u2) + (u1 * x2) - (x1 * u2) - (x0 * u1) - (u0 * x2); - var deltaC = (u0 * v1 * x2) + (v0 * x1 * u2) + (x0 * u1 * v2) - (x0 * v1 * u2) - (v0 * u1 * x2) - (u0 * x1 * v2); - var deltaD = (y0 * v1) + (v0 * y2) + (y1 * v2) - (v1 * y2) - (v0 * y1) - (y0 * v2); - var deltaE = (u0 * y1) + (y0 * u2) + (u1 * y2) - (y1 * u2) - (y0 * u1) - (u0 * y2); - var deltaF = (u0 * v1 * y2) + (v0 * y1 * u2) + (y0 * u1 * v2) - (y0 * v1 * u2) - (v0 * u1 * y2) - (u0 * y1 * v2); - - context.transform(deltaA / delta, deltaD / delta, - deltaB / delta, deltaE / delta, - deltaC / delta, deltaF / delta); - - context.drawImage(textureSource, 0, 0); - context.restore(); -}; - - - -/** - * Renders a flat Mesh - * - * @param Mesh {Mesh} The Mesh to render - * @private - */ -Mesh.prototype.renderMeshFlat = function (Mesh) -{ - var context = this.context; - var vertices = Mesh.vertices; - - var length = vertices.length/2; - // this.count++; - - context.beginPath(); - for (var i=1; i < length-2; i++) - { - // draw some triangles! - var index = i*2; - - var x0 = vertices[index], x1 = vertices[index+2], x2 = vertices[index+4]; - var y0 = vertices[index+1], y1 = vertices[index+3], y2 = vertices[index+5]; - - context.moveTo(x0, y0); - context.lineTo(x1, y1); - context.lineTo(x2, y2); - } - - context.fillStyle = '#FF0000'; - context.fill(); - context.closePath(); -}; - -/* -Mesh.prototype.setTexture = function (texture) -{ - //TODO SET THE TEXTURES - //TODO VISIBILITY - //TODO SETTER - - // stop current texture - this.texture = texture; - this.width = texture.frame.width; - this.height = texture.frame.height; - this.updateFrame = true; -}; - */ - -/** - * When the texture is updated, this event will fire to update the scale and frame - * - * @param event - * @private - */ - -Mesh.prototype.onTextureUpdate = function () -{ - this.updateFrame = true; -}; - -/** - * Returns the bounds of the mesh as a rectangle. The bounds calculation takes the worldTransform into account. - * - * @param matrix {Matrix} the transformation matrix of the sprite - * @return {Rectangle} the framing rectangle - */ -Mesh.prototype.getBounds = function (matrix) -{ - var worldTransform = matrix || this.worldTransform; - - var a = worldTransform.a; - var b = worldTransform.b; - var c = worldTransform.c; - var d = worldTransform.d; - var tx = worldTransform.tx; - var ty = worldTransform.ty; - - var maxX = -Infinity; - var maxY = -Infinity; - - var minX = Infinity; - var minY = Infinity; - - var vertices = this.vertices; - for (var i = 0, n = vertices.length; i < n; i += 2) - { - var rawX = vertices[i], rawY = vertices[i + 1]; - var x = (a * rawX) + (c * rawY) + tx; - var y = (d * rawY) + (b * rawX) + ty; - - minX = x < minX ? x : minX; - minY = y < minY ? y : minY; - - maxX = x > maxX ? x : maxX; - maxY = y > maxY ? y : maxY; - } - - if (minX === -Infinity || maxY === Infinity) - { - return core.math.Rectangle.EMPTY; - } - - var bounds = this._bounds; - - bounds.x = minX; - bounds.width = maxX - minX; - - bounds.y = minY; - bounds.height = maxY - minY; - - // store a reference so that if this function gets called again in the render cycle we do not have to recalculate - this._currentBounds = bounds; - - return bounds; -}; - -/** - * Different drawing buffer modes supported - * - * @static - * @constant - * @property {object} DRAW_MODES - * @property {number} DRAW_MODES.TRIANGLE_MESH - * @property {number} DRAW_MODES.TRIANGLES - */ -Mesh.DRAW_MODES = { - TRIANGLE_MESH: 0, - TRIANGLES: 1 -}; diff --git a/src/extras/mesh/Rope.js b/src/extras/mesh/Rope.js deleted file mode 100644 index 8119995..0000000 --- a/src/extras/mesh/Rope.js +++ /dev/null @@ -1,192 +0,0 @@ -var Mesh = require('./Mesh'); - -/** - * The rope allows you to draw a texture across several points and them manipulate these points - * - *```js - * for (var i = 0; i < 20; i++) { - * points.push(new PIXI.Point(i * 50, 0)); - * }; - * var rope = new PIXI.Rope(PIXI.Texture.fromImage("snake.png"), points); - * ``` - * - * @class - * @extends Mesh - * @memberof PIXI.extras - * @param {Texture} texture - The texture to use on the rope. - * @param {Array} points - An array of {Point} objects to construct this rope. - * - */ -function Rope(texture, points) -{ - Mesh.call(this, texture); - - /* - * @member {Array} An array of points that determine the rope - */ - this.points = points; - - /* - * @member {Float32Array} An array of vertices used to construct this rope. - */ - this.vertices = new Float32Array(points.length * 4); - - /* - * @member {Float32Array} The WebGL Uvs of the rope. - */ - this.uvs = new Float32Array(points.length * 4); - - /* - * @member {Float32Array} An array containing the color components - */ - this.colors = new Float32Array(points.length * 2); - - /* - * @member {Uint16Array} An array containing the indices of the vertices - */ - this.indices = new Uint16Array(points.length * 2); - - this.refresh(); -} - - -// constructor -Rope.prototype = Object.create(Mesh.prototype); -Rope.prototype.constructor = Rope; -module.exports = Rope; - -/** - * Refreshes - * - */ -Rope.prototype.refresh = function () -{ - var points = this.points; - - if (points.length < 1) - { - return; - } - - var uvs = this.uvs; - - var indices = this.indices; - var colors = this.colors; - - // this.count -= 0.2; - - uvs[0] = 0; - uvs[1] = 0; - uvs[2] = 0; - uvs[3] = 1; - - colors[0] = 1; - colors[1] = 1; - - indices[0] = 0; - indices[1] = 1; - - var total = points.length, - point, index, amount; - - for (var i = 1; i < total; i++) - { - point = points[i]; - index = i * 4; - // time to do some smart drawing! - amount = i / (total-1); - - if (i%2) - { - uvs[index] = amount; - uvs[index+1] = 0; - - uvs[index+2] = amount; - uvs[index+3] = 1; - } - else - { - uvs[index] = amount; - uvs[index+1] = 0; - - uvs[index+2] = amount; - uvs[index+3] = 1; - } - - index = i * 2; - colors[index] = 1; - colors[index+1] = 1; - - index = i * 2; - indices[index] = index; - indices[index + 1] = index + 1; - } -}; - -/* - * Updates the object transform for rendering - * - * @private - */ -Rope.prototype.updateTransform = function () -{ - var points = this.points; - - if (points.length < 1) - { - return; - } - - var lastPoint = points[0]; - var nextPoint; - var perpX = 0; - var perpY = 0; - - // this.count -= 0.2; - - var vertices = this.vertices; - var total = points.length, - point, index, ratio, perpLength, num; - - for (var i = 0; i < total; i++) - { - point = points[i]; - index = i * 4; - - if (i < points.length-1) - { - nextPoint = points[i+1]; - } - else - { - nextPoint = point; - } - - perpY = -(nextPoint.x - lastPoint.x); - perpX = nextPoint.y - lastPoint.y; - - ratio = (1 - (i / (total-1))) * 10; - - if (ratio > 1) - { - ratio = 1; - } - - perpLength = Math.sqrt(perpX * perpX + perpY * perpY); - num = this.texture.height / 2; //(20 + Math.abs(Math.sin((i + this.count) * 0.3) * 50) )* ratio; - perpX /= perpLength; - perpY /= perpLength; - - perpX *= num; - perpY *= num; - - vertices[index] = point.x + perpX; - vertices[index+1] = point.y + perpY; - vertices[index+2] = point.x - perpX; - vertices[index+3] = point.y - perpY; - - lastPoint = point; - } - - this.containerUpdateTransform(); -}; diff --git a/src/extras/mesh/index.js b/src/extras/mesh/index.js deleted file mode 100644 index dd37f87..0000000 --- a/src/extras/mesh/index.js +++ /dev/null @@ -1,16 +0,0 @@ -/** - * @file Main export of the PIXI extras library - * @author Mat Groves - * @copyright 2013-2015 GoodBoyDigital - * @license {@link https://github.com/GoodBoyDigital/pixi.js/blob/master/LICENSE|MIT License} - */ - -/** - * @namespace PIXI.extras - */ -module.exports = { - Mesh: require('./Mesh'), - Rope: require('./Rope'), - MeshRenderer: require('./webgl/MeshRenderer'), - MeshShader: require('./webgl/MeshShader') -}; diff --git a/src/extras/mesh/webgl/MeshRenderer.js b/src/extras/mesh/webgl/MeshRenderer.js deleted file mode 100644 index 2dd7678..0000000 --- a/src/extras/mesh/webgl/MeshRenderer.js +++ /dev/null @@ -1,215 +0,0 @@ -var ObjectRenderer = require('../../../core/renderers/webgl/utils/ObjectRenderer'), - WebGLRenderer = require('../../../core/renderers/webgl/WebGLRenderer'); - -/** - * @author Mat Groves - * - * Big thanks to the very clever Matt DesLauriers https://github.com/mattdesl/ - * for creating the original pixi version! - * Also a thanks to https://github.com/bchevalier for tweaking the tint and alpha so that they now share 4 bytes on the vertex buffer - * - * Heavily inspired by LibGDX's MeshRenderer: - * https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/graphics/g2d/MeshRenderer.java - */ - -/** - * - * @class - * @private - * @memberof PIXI - * @extends ObjectRenderer - * @param renderer {WebGLRenderer} The renderer this sprite batch works for. - */ -function MeshRenderer(renderer) -{ - ObjectRenderer.call(this, renderer); - - - /** - * Holds the indices - * - * @member {Uint16Array} - */ - this.indices = new Uint16Array(15000); - - //TODO this could be a single buffer shared amongst all renderers as we reuse this set up in most renderers - for (var i=0, j=0; i < 15000; i += 6, j += 4) - { - this.indices[i + 0] = j + 0; - this.indices[i + 1] = j + 1; - this.indices[i + 2] = j + 2; - this.indices[i + 3] = j + 0; - this.indices[i + 4] = j + 2; - this.indices[i + 5] = j + 3; - } -} - -MeshRenderer.prototype = Object.create(ObjectRenderer.prototype); -MeshRenderer.prototype.constructor = MeshRenderer; -module.exports = MeshRenderer; - -WebGLRenderer.registerPlugin('mesh', MeshRenderer); - -/** - * Sets up the renderer context and necessary buffers. - * - * @private - * @param gl {WebGLRenderingContext} the current WebGL drawing context - */ -MeshRenderer.prototype.onContextChange = function () -{ - -}; - -/** - * Renders the sprite object. - * - * @param mesh {Mesh} the mesh to render - */ -MeshRenderer.prototype.render = function (mesh) -{ -// return; - if(!mesh._vertexBuffer) - { - this._initWebGL(mesh); - } - - var renderer = this.renderer, - gl = renderer.gl, - texture = mesh.texture.baseTexture, - shader = renderer.shaderManager.plugins.meshShader; - -// var drawMode = mesh.drawMode === Strip.DRAW_MODES.TRIANGLE_STRIP ? gl.TRIANGLE_STRIP : gl.TRIANGLES; - var drawMode = gl.TRIANGLE_STRIP; - - renderer.blendModeManager.setBlendMode(mesh.blendMode); - - - // set uniforms - gl.uniformMatrix3fv(shader.uniforms.translationMatrix._location, false, mesh.worldTransform.toArray(true)); - - gl.uniformMatrix3fv(shader.uniforms.projectionMatrix._location, false, renderer.currentRenderTarget.projectionMatrix.toArray(true)); - gl.uniform1f(shader.uniforms.alpha._location, mesh.worldAlpha); - - if (!mesh.dirty) - { - - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._vertexBuffer); - gl.bufferSubData(gl.ARRAY_BUFFER, 0, mesh.vertices); - gl.vertexAttribPointer(shader.attributes.aVertexPosition, 2, gl.FLOAT, false, 0, 0); - - - // update the uvs - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._uvBuffer); - gl.vertexAttribPointer(shader.attributes.aTextureCoord, 2, gl.FLOAT, false, 0, 0); - - - gl.activeTexture(gl.TEXTURE0); - - if (!texture._glTextures[gl.id]) - { - this.renderer.updateTexture(texture); - } - else - { - // bind the current texture - gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]); - } - } - else - { - - mesh.dirty = false; - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER, mesh.vertices, gl.STATIC_DRAW); - gl.vertexAttribPointer(shader.attributes.aVertexPosition, 2, gl.FLOAT, false, 0, 0); - - // update the uvs - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._uvBuffer); - gl.bufferData(gl.ARRAY_BUFFER, mesh.uvs, gl.STATIC_DRAW); - gl.vertexAttribPointer(shader.attributes.aTextureCoord, 2, gl.FLOAT, false, 0, 0); - - gl.activeTexture(gl.TEXTURE0); - - if (!texture._glTextures[gl.id]) - { - this.renderer.updateTexture(texture); - } - else - { - // bind the current texture - gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]); - } - - // dont need to upload! - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, mesh._indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, mesh.indices, gl.STATIC_DRAW); - - } - - gl.drawElements(drawMode, mesh.indices.length, gl.UNSIGNED_SHORT, 0); - -}; - -/** - * Prepares all the buffers to render this mesh - * @param mesh {Mesh} the mesh to render - */ -MeshRenderer.prototype._initWebGL = function (mesh) -{ - // build the strip! - var gl = this.renderer.gl; - - mesh._vertexBuffer = gl.createBuffer(); - mesh._indexBuffer = gl.createBuffer(); - mesh._uvBuffer = gl.createBuffer(); - mesh._colorBuffer = gl.createBuffer(); - - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER, mesh.vertices, gl.DYNAMIC_DRAW); - - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._uvBuffer); - gl.bufferData(gl.ARRAY_BUFFER, mesh.uvs, gl.STATIC_DRAW); - - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._colorBuffer); - gl.bufferData(gl.ARRAY_BUFFER, mesh.colors, gl.STATIC_DRAW); - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, mesh._indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, mesh.indices, gl.STATIC_DRAW); -}; - - -/** - * Empties the current batch. - * - */ -MeshRenderer.prototype.flush = function () -{ - -}; - -/** - * Starts a new mesh renderer. - * - */ -MeshRenderer.prototype.start = function () -{ - var gl = this.renderer.gl, - shader = this.renderer.shaderManager.plugins.meshShader; - - this.renderer.shaderManager.setShader(shader); - - // dont need to upload! - //gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indices); - - - // this.s -}; - -/** - * Destroys the Mesh renderer - * - */ -MeshRenderer.prototype.destroy = function () -{ -}; diff --git a/src/extras/mesh/webgl/MeshShader.js b/src/extras/mesh/webgl/MeshShader.js deleted file mode 100644 index 51c03f5..0000000 --- a/src/extras/mesh/webgl/MeshShader.js +++ /dev/null @@ -1,59 +0,0 @@ -var core = require('../../../core'); - -/** - * @class - * @extends Shader - * @memberof PIXI.extras - * @param shaderManager {ShaderManager} The WebGL shader manager this shader works for. - */ -function StripShader(shaderManager) -{ - core.Shader.call(this, - shaderManager, - // vertex shader - [ - 'precision lowp float;', - 'attribute vec2 aVertexPosition;', - 'attribute vec2 aTextureCoord;', - - 'uniform mat3 translationMatrix;', - 'uniform mat3 projectionMatrix;', - - 'varying vec2 vTextureCoord;', - - 'void main(void){', - ' gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);', - ' vTextureCoord = aTextureCoord;', - '}' - ].join('\n'), - [ - 'precision lowp float;', - - 'varying vec2 vTextureCoord;', - 'uniform float alpha;', - - 'uniform sampler2D uSampler;', - - 'void main(void){', - ' gl_FragColor = texture2D(uSampler, vTextureCoord) * alpha ;', - '}' - ].join('\n'), - // custom uniforms - { - alpha: { type: '1f', value: 0 }, - translationMatrix: { type: 'mat3', value: new Float32Array(9) }, - projectionMatrix: { type: 'mat3', value: new Float32Array(9) } - }, - // custom attributes - { - aVertexPosition:0, - aTextureCoord:0 - } - ); -} - -StripShader.prototype = Object.create(core.Shader.prototype); -StripShader.prototype.constructor = StripShader; -module.exports = StripShader; - -core.ShaderManager.registerPlugin('meshShader', StripShader); diff --git a/src/index.js b/src/index.js index 2c1f999..da8c001 100644 --- a/src/index.js +++ b/src/index.js @@ -1,6 +1,7 @@ var core = require('./core'); extendCore(require('./extras')); +extendCore(require('./mesh')); extendCore(require('./filters')); extendCore(require('./interaction')); extendCore(require('./loaders')); diff --git a/src/mesh/Mesh.js b/src/mesh/Mesh.js new file mode 100644 index 0000000..c006078 --- /dev/null +++ b/src/mesh/Mesh.js @@ -0,0 +1,387 @@ +var core = require('../core'); + +/** + * Base mesh class + * @class + * @extends Container + * @memberof PIXI.extras + * @param texture {Texture} The texture to use + * @param [vertices] {Float32Arrif you want to specify the vertices + * @param [uvs] {Float32Array} if you want to specify the uvs + * @param [indices] {Uint16Array} if you want to specify the indices + * @param [drawMode] {number} the drawMode, can be any of the Mesh.DRAW_MODES consts + */ +function Mesh(texture, vertices, uvs, indices, drawMode) +{ + core.Container.call(this); + + /** + * The texture of the Mesh + * + * @member {Texture} + */ + this.texture = texture; + + /** + * The Uvs of the Mesh + * + * @member {Float32Array} + */ + this.uvs = uvs || new Float32Array([0, 1, + 1, 1, + 1, 0, + 0, 1]); + + /** + * An array of vertices + * + * @member {Float32Array} + */ + this.vertices = vertices || new Float32Array([0, 0, + 100, 0, + 100, 100, + 0, 100]); + + /* + * @member {Uint16Array} An array containing the indices of the vertices + */ + // TODO auto generate this based on draw mode! + this.indices = indices || new Uint16Array([0, 1, 2, 3]); + + /** + * Whether the Mesh is dirty or not + * + * @member {boolean} + */ + this.dirty = true; + + /** + * The blend mode to be applied to the sprite. Set to blendModes.NORMAL to remove any blend mode. + * + * @member {number} + * @default CONST.BLEND_MODES.NORMAL; + */ + this.blendMode = core.CONST.BLEND_MODES.NORMAL; + + /** + * Triangles in canvas mode are automatically antialiased, use this value to force triangles to overlap a bit with each other. + * + * @member {number}= + */ + this.canvasPadding = 0; + + /** + * The way the Mesh should be drawn, can be any of the Mesh.DRAW_MODES consts + * + * @member {number} + */ + this.drawMode = drawMode || Mesh.DRAW_MODES.TRIANGLE_MESH; +} + +// constructor +Mesh.prototype = Object.create(core.Container.prototype); +Mesh.prototype.constructor = Mesh; +module.exports = Mesh; + +/** + * Renders the object using the WebGL renderer + * + * @param renderer {WebGLRenderer} a reference to the WebGL renderer + */ +Mesh.prototype._renderWebGL = function (renderer) +{ + renderer.setObjectRenderer(renderer.plugins.mesh); + renderer.plugins.mesh.render(this); +}; + +/** + * Renders the object using the Canvas renderer + * + * @param renderer {CanvasRenderer} + */ +Mesh.prototype._renderCanvas = function (renderer) +{ + var context = renderer.context; + + var transform = this.worldTransform; + + if (renderer.roundPixels) + { + context.setTransform(transform.a, transform.b, transform.c, transform.d, transform.tx | 0, transform.ty | 0); + } + else + { + context.setTransform(transform.a, transform.b, transform.c, transform.d, transform.tx, transform.ty); + } + + if (this.drawMode === Mesh.DRAW_MODES.TRIANGLE_MESH) + { + this._renderCanvasTriangleMesh(context); + } + else + { + this._renderCanvasTriangles(context); + } +}; + +/** + * Draws the object in Triangle Mesh mode using canvas + * + * @param context {CanvasRenderingContext2D} the current drawing context + * @private + */ +Mesh.prototype._renderCanvasTriangleMesh = function (context) +{ + // draw triangles!! + var vertices = this.vertices; + var uvs = this.uvs; + + var length = vertices.length / 2; + // this.count++; + + for (var i = 0; i < length - 2; i++) + { + // draw some triangles! + var index = i * 2; + this._renderCanvasDrawTriangle(context, vertices, uvs, index, (index + 2), (index + 4)); + } +}; + +/** + * Draws the object in triangle mode using canvas + * + * @param context {CanvasRenderingContext2D} the current drawing context + * @private + */ +Mesh.prototype._renderCanvasTriangles = function (context) +{ + // draw triangles!! + var vertices = this.vertices; + var uvs = this.uvs; + var indices = this.indices; + + var length = indices.length; + // this.count++; + + for (var i = 0; i < length; i += 3) + { + // draw some triangles! + var index0 = indices[i] * 2, index1 = indices[i + 1] * 2, index2 = indices[i + 2] * 2; + this._renderCanvasDrawTriangle(context, vertices, uvs, index0, index1, index2); + } +}; + +/** + * Draws one of the triangles that form this Mesh + * + * @param context {CanvasRenderingContext2D} the current drawing context + * @param vertices {Float32Array} a reference to the vertices of the Mesh + * @param uvs {Float32Array} a reference to the uvs of the Mesh + * @param index0 {number} the index of the first vertex + * @param index1 {number} the index of the second vertex + * @param index2 {number} the index of the third vertex + * @private + */ +Mesh.prototype._renderCanvasDrawTriangle = function (context, vertices, uvs, index0, index1, index2) +{ + var textureSource = this.texture.baseTexture.source; + var textureWidth = this.texture.width; + var textureHeight = this.texture.height; + + var x0 = vertices[index0], x1 = vertices[index1], x2 = vertices[index2]; + var y0 = vertices[index0 + 1], y1 = vertices[index1 + 1], y2 = vertices[index2 + 1]; + + var u0 = uvs[index0] * textureWidth, u1 = uvs[index1] * textureWidth, u2 = uvs[index2] * textureWidth; + var v0 = uvs[index0 + 1] * textureHeight, v1 = uvs[index1 + 1] * textureHeight, v2 = uvs[index2 + 1] * textureHeight; + + if (this.canvasPadding > 0) + { + var paddingX = this.canvasPadding / this.worldTransform.a; + var paddingY = this.canvasPadding / this.worldTransform.d; + var centerX = (x0 + x1 + x2) / 3; + var centerY = (y0 + y1 + y2) / 3; + + var normX = x0 - centerX; + var normY = y0 - centerY; + + var dist = Math.sqrt(normX * normX + normY * normY); + x0 = centerX + (normX / dist) * (dist + paddingX); + y0 = centerY + (normY / dist) * (dist + paddingY); + + // + + normX = x1 - centerX; + normY = y1 - centerY; + + dist = Math.sqrt(normX * normX + normY * normY); + x1 = centerX + (normX / dist) * (dist + paddingX); + y1 = centerY + (normY / dist) * (dist + paddingY); + + normX = x2 - centerX; + normY = y2 - centerY; + + dist = Math.sqrt(normX * normX + normY * normY); + x2 = centerX + (normX / dist) * (dist + paddingX); + y2 = centerY + (normY / dist) * (dist + paddingY); + } + + context.save(); + context.beginPath(); + + + context.moveTo(x0, y0); + context.lineTo(x1, y1); + context.lineTo(x2, y2); + + context.closePath(); + + context.clip(); + + // Compute matrix transform + var delta = (u0 * v1) + (v0 * u2) + (u1 * v2) - (v1 * u2) - (v0 * u1) - (u0 * v2); + var deltaA = (x0 * v1) + (v0 * x2) + (x1 * v2) - (v1 * x2) - (v0 * x1) - (x0 * v2); + var deltaB = (u0 * x1) + (x0 * u2) + (u1 * x2) - (x1 * u2) - (x0 * u1) - (u0 * x2); + var deltaC = (u0 * v1 * x2) + (v0 * x1 * u2) + (x0 * u1 * v2) - (x0 * v1 * u2) - (v0 * u1 * x2) - (u0 * x1 * v2); + var deltaD = (y0 * v1) + (v0 * y2) + (y1 * v2) - (v1 * y2) - (v0 * y1) - (y0 * v2); + var deltaE = (u0 * y1) + (y0 * u2) + (u1 * y2) - (y1 * u2) - (y0 * u1) - (u0 * y2); + var deltaF = (u0 * v1 * y2) + (v0 * y1 * u2) + (y0 * u1 * v2) - (y0 * v1 * u2) - (v0 * u1 * y2) - (u0 * y1 * v2); + + context.transform(deltaA / delta, deltaD / delta, + deltaB / delta, deltaE / delta, + deltaC / delta, deltaF / delta); + + context.drawImage(textureSource, 0, 0); + context.restore(); +}; + + + +/** + * Renders a flat Mesh + * + * @param Mesh {Mesh} The Mesh to render + * @private + */ +Mesh.prototype.renderMeshFlat = function (Mesh) +{ + var context = this.context; + var vertices = Mesh.vertices; + + var length = vertices.length/2; + // this.count++; + + context.beginPath(); + for (var i=1; i < length-2; i++) + { + // draw some triangles! + var index = i*2; + + var x0 = vertices[index], x1 = vertices[index+2], x2 = vertices[index+4]; + var y0 = vertices[index+1], y1 = vertices[index+3], y2 = vertices[index+5]; + + context.moveTo(x0, y0); + context.lineTo(x1, y1); + context.lineTo(x2, y2); + } + + context.fillStyle = '#FF0000'; + context.fill(); + context.closePath(); +}; + +/* +Mesh.prototype.setTexture = function (texture) +{ + //TODO SET THE TEXTURES + //TODO VISIBILITY + //TODO SETTER + + // stop current texture + this.texture = texture; + this.width = texture.frame.width; + this.height = texture.frame.height; + this.updateFrame = true; +}; + */ + +/** + * When the texture is updated, this event will fire to update the scale and frame + * + * @param event + * @private + */ + +Mesh.prototype.onTextureUpdate = function () +{ + this.updateFrame = true; +}; + +/** + * Returns the bounds of the mesh as a rectangle. The bounds calculation takes the worldTransform into account. + * + * @param matrix {Matrix} the transformation matrix of the sprite + * @return {Rectangle} the framing rectangle + */ +Mesh.prototype.getBounds = function (matrix) +{ + var worldTransform = matrix || this.worldTransform; + + var a = worldTransform.a; + var b = worldTransform.b; + var c = worldTransform.c; + var d = worldTransform.d; + var tx = worldTransform.tx; + var ty = worldTransform.ty; + + var maxX = -Infinity; + var maxY = -Infinity; + + var minX = Infinity; + var minY = Infinity; + + var vertices = this.vertices; + for (var i = 0, n = vertices.length; i < n; i += 2) + { + var rawX = vertices[i], rawY = vertices[i + 1]; + var x = (a * rawX) + (c * rawY) + tx; + var y = (d * rawY) + (b * rawX) + ty; + + minX = x < minX ? x : minX; + minY = y < minY ? y : minY; + + maxX = x > maxX ? x : maxX; + maxY = y > maxY ? y : maxY; + } + + if (minX === -Infinity || maxY === Infinity) + { + return core.math.Rectangle.EMPTY; + } + + var bounds = this._bounds; + + bounds.x = minX; + bounds.width = maxX - minX; + + bounds.y = minY; + bounds.height = maxY - minY; + + // store a reference so that if this function gets called again in the render cycle we do not have to recalculate + this._currentBounds = bounds; + + return bounds; +}; + +/** + * Different drawing buffer modes supported + * + * @static + * @constant + * @property {object} DRAW_MODES + * @property {number} DRAW_MODES.TRIANGLE_MESH + * @property {number} DRAW_MODES.TRIANGLES + */ +Mesh.DRAW_MODES = { + TRIANGLE_MESH: 0, + TRIANGLES: 1 +}; diff --git a/src/mesh/Rope.js b/src/mesh/Rope.js new file mode 100644 index 0000000..8119995 --- /dev/null +++ b/src/mesh/Rope.js @@ -0,0 +1,192 @@ +var Mesh = require('./Mesh'); + +/** + * The rope allows you to draw a texture across several points and them manipulate these points + * + *```js + * for (var i = 0; i < 20; i++) { + * points.push(new PIXI.Point(i * 50, 0)); + * }; + * var rope = new PIXI.Rope(PIXI.Texture.fromImage("snake.png"), points); + * ``` + * + * @class + * @extends Mesh + * @memberof PIXI.extras + * @param {Texture} texture - The texture to use on the rope. + * @param {Array} points - An array of {Point} objects to construct this rope. + * + */ +function Rope(texture, points) +{ + Mesh.call(this, texture); + + /* + * @member {Array} An array of points that determine the rope + */ + this.points = points; + + /* + * @member {Float32Array} An array of vertices used to construct this rope. + */ + this.vertices = new Float32Array(points.length * 4); + + /* + * @member {Float32Array} The WebGL Uvs of the rope. + */ + this.uvs = new Float32Array(points.length * 4); + + /* + * @member {Float32Array} An array containing the color components + */ + this.colors = new Float32Array(points.length * 2); + + /* + * @member {Uint16Array} An array containing the indices of the vertices + */ + this.indices = new Uint16Array(points.length * 2); + + this.refresh(); +} + + +// constructor +Rope.prototype = Object.create(Mesh.prototype); +Rope.prototype.constructor = Rope; +module.exports = Rope; + +/** + * Refreshes + * + */ +Rope.prototype.refresh = function () +{ + var points = this.points; + + if (points.length < 1) + { + return; + } + + var uvs = this.uvs; + + var indices = this.indices; + var colors = this.colors; + + // this.count -= 0.2; + + uvs[0] = 0; + uvs[1] = 0; + uvs[2] = 0; + uvs[3] = 1; + + colors[0] = 1; + colors[1] = 1; + + indices[0] = 0; + indices[1] = 1; + + var total = points.length, + point, index, amount; + + for (var i = 1; i < total; i++) + { + point = points[i]; + index = i * 4; + // time to do some smart drawing! + amount = i / (total-1); + + if (i%2) + { + uvs[index] = amount; + uvs[index+1] = 0; + + uvs[index+2] = amount; + uvs[index+3] = 1; + } + else + { + uvs[index] = amount; + uvs[index+1] = 0; + + uvs[index+2] = amount; + uvs[index+3] = 1; + } + + index = i * 2; + colors[index] = 1; + colors[index+1] = 1; + + index = i * 2; + indices[index] = index; + indices[index + 1] = index + 1; + } +}; + +/* + * Updates the object transform for rendering + * + * @private + */ +Rope.prototype.updateTransform = function () +{ + var points = this.points; + + if (points.length < 1) + { + return; + } + + var lastPoint = points[0]; + var nextPoint; + var perpX = 0; + var perpY = 0; + + // this.count -= 0.2; + + var vertices = this.vertices; + var total = points.length, + point, index, ratio, perpLength, num; + + for (var i = 0; i < total; i++) + { + point = points[i]; + index = i * 4; + + if (i < points.length-1) + { + nextPoint = points[i+1]; + } + else + { + nextPoint = point; + } + + perpY = -(nextPoint.x - lastPoint.x); + perpX = nextPoint.y - lastPoint.y; + + ratio = (1 - (i / (total-1))) * 10; + + if (ratio > 1) + { + ratio = 1; + } + + perpLength = Math.sqrt(perpX * perpX + perpY * perpY); + num = this.texture.height / 2; //(20 + Math.abs(Math.sin((i + this.count) * 0.3) * 50) )* ratio; + perpX /= perpLength; + perpY /= perpLength; + + perpX *= num; + perpY *= num; + + vertices[index] = point.x + perpX; + vertices[index+1] = point.y + perpY; + vertices[index+2] = point.x - perpX; + vertices[index+3] = point.y - perpY; + + lastPoint = point; + } + + this.containerUpdateTransform(); +}; diff --git a/src/extras/index.js b/src/extras/index.js index 267e97c..6f14e0d 100644 --- a/src/extras/index.js +++ b/src/extras/index.js @@ -11,7 +11,6 @@ module.exports = { MovieClip: require('./MovieClip'), TilingSprite: require('./TilingSprite'), - mesh: require('./mesh/index'), cacheAsBitmap: require('./cacheAsBitmap'), getChildByName: require('./getChildByName') }; diff --git a/src/extras/mesh/Mesh.js b/src/extras/mesh/Mesh.js deleted file mode 100644 index 30431ae..0000000 --- a/src/extras/mesh/Mesh.js +++ /dev/null @@ -1,387 +0,0 @@ -var core = require('../../core'); - -/** - * Base mesh class - * @class - * @extends Container - * @memberof PIXI.extras - * @param texture {Texture} The texture to use - * @param [vertices] {Float32Arrif you want to specify the vertices - * @param [uvs] {Float32Array} if you want to specify the uvs - * @param [indices] {Uint16Array} if you want to specify the indices - * @param [drawMode] {number} the drawMode, can be any of the Mesh.DRAW_MODES consts - */ -function Mesh(texture, vertices, uvs, indices, drawMode) -{ - core.Container.call(this); - - /** - * The texture of the Mesh - * - * @member {Texture} - */ - this.texture = texture; - - /** - * The Uvs of the Mesh - * - * @member {Float32Array} - */ - this.uvs = uvs || new Float32Array([0, 1, - 1, 1, - 1, 0, - 0, 1]); - - /** - * An array of vertices - * - * @member {Float32Array} - */ - this.vertices = vertices || new Float32Array([0, 0, - 100, 0, - 100, 100, - 0, 100]); - - /* - * @member {Uint16Array} An array containing the indices of the vertices - */ - // TODO auto generate this based on draw mode! - this.indices = indices || new Uint16Array([0, 1, 2, 3]); - - /** - * Whether the Mesh is dirty or not - * - * @member {boolean} - */ - this.dirty = true; - - /** - * The blend mode to be applied to the sprite. Set to blendModes.NORMAL to remove any blend mode. - * - * @member {number} - * @default CONST.BLEND_MODES.NORMAL; - */ - this.blendMode = core.CONST.BLEND_MODES.NORMAL; - - /** - * Triangles in canvas mode are automatically antialiased, use this value to force triangles to overlap a bit with each other. - * - * @member {number}= - */ - this.canvasPadding = 0; - - /** - * The way the Mesh should be drawn, can be any of the Mesh.DRAW_MODES consts - * - * @member {number} - */ - this.drawMode = drawMode || Mesh.DRAW_MODES.TRIANGLE_MESH; -} - -// constructor -Mesh.prototype = Object.create(core.Container.prototype); -Mesh.prototype.constructor = Mesh; -module.exports = Mesh; - -/** - * Renders the object using the WebGL renderer - * - * @param renderer {WebGLRenderer} a reference to the WebGL renderer - */ -Mesh.prototype._renderWebGL = function (renderer) -{ - renderer.setObjectRenderer(renderer.plugins.mesh); - renderer.plugins.mesh.render(this); -}; - -/** - * Renders the object using the Canvas renderer - * - * @param renderer {CanvasRenderer} - */ -Mesh.prototype._renderCanvas = function (renderer) -{ - var context = renderer.context; - - var transform = this.worldTransform; - - if (renderer.roundPixels) - { - context.setTransform(transform.a, transform.b, transform.c, transform.d, transform.tx | 0, transform.ty | 0); - } - else - { - context.setTransform(transform.a, transform.b, transform.c, transform.d, transform.tx, transform.ty); - } - - if (this.drawMode === Mesh.DRAW_MODES.TRIANGLE_MESH) - { - this._renderCanvasTriangleMesh(context); - } - else - { - this._renderCanvasTriangles(context); - } -}; - -/** - * Draws the object in Triangle Mesh mode using canvas - * - * @param context {CanvasRenderingContext2D} the current drawing context - * @private - */ -Mesh.prototype._renderCanvasTriangleMesh = function (context) -{ - // draw triangles!! - var vertices = this.vertices; - var uvs = this.uvs; - - var length = vertices.length / 2; - // this.count++; - - for (var i = 0; i < length - 2; i++) - { - // draw some triangles! - var index = i * 2; - this._renderCanvasDrawTriangle(context, vertices, uvs, index, (index + 2), (index + 4)); - } -}; - -/** - * Draws the object in triangle mode using canvas - * - * @param context {CanvasRenderingContext2D} the current drawing context - * @private - */ -Mesh.prototype._renderCanvasTriangles = function (context) -{ - // draw triangles!! - var vertices = this.vertices; - var uvs = this.uvs; - var indices = this.indices; - - var length = indices.length; - // this.count++; - - for (var i = 0; i < length; i += 3) - { - // draw some triangles! - var index0 = indices[i] * 2, index1 = indices[i + 1] * 2, index2 = indices[i + 2] * 2; - this._renderCanvasDrawTriangle(context, vertices, uvs, index0, index1, index2); - } -}; - -/** - * Draws one of the triangles that form this Mesh - * - * @param context {CanvasRenderingContext2D} the current drawing context - * @param vertices {Float32Array} a reference to the vertices of the Mesh - * @param uvs {Float32Array} a reference to the uvs of the Mesh - * @param index0 {number} the index of the first vertex - * @param index1 {number} the index of the second vertex - * @param index2 {number} the index of the third vertex - * @private - */ -Mesh.prototype._renderCanvasDrawTriangle = function (context, vertices, uvs, index0, index1, index2) -{ - var textureSource = this.texture.baseTexture.source; - var textureWidth = this.texture.width; - var textureHeight = this.texture.height; - - var x0 = vertices[index0], x1 = vertices[index1], x2 = vertices[index2]; - var y0 = vertices[index0 + 1], y1 = vertices[index1 + 1], y2 = vertices[index2 + 1]; - - var u0 = uvs[index0] * textureWidth, u1 = uvs[index1] * textureWidth, u2 = uvs[index2] * textureWidth; - var v0 = uvs[index0 + 1] * textureHeight, v1 = uvs[index1 + 1] * textureHeight, v2 = uvs[index2 + 1] * textureHeight; - - if (this.canvasPadding > 0) - { - var paddingX = this.canvasPadding / this.worldTransform.a; - var paddingY = this.canvasPadding / this.worldTransform.d; - var centerX = (x0 + x1 + x2) / 3; - var centerY = (y0 + y1 + y2) / 3; - - var normX = x0 - centerX; - var normY = y0 - centerY; - - var dist = Math.sqrt(normX * normX + normY * normY); - x0 = centerX + (normX / dist) * (dist + paddingX); - y0 = centerY + (normY / dist) * (dist + paddingY); - - // - - normX = x1 - centerX; - normY = y1 - centerY; - - dist = Math.sqrt(normX * normX + normY * normY); - x1 = centerX + (normX / dist) * (dist + paddingX); - y1 = centerY + (normY / dist) * (dist + paddingY); - - normX = x2 - centerX; - normY = y2 - centerY; - - dist = Math.sqrt(normX * normX + normY * normY); - x2 = centerX + (normX / dist) * (dist + paddingX); - y2 = centerY + (normY / dist) * (dist + paddingY); - } - - context.save(); - context.beginPath(); - - - context.moveTo(x0, y0); - context.lineTo(x1, y1); - context.lineTo(x2, y2); - - context.closePath(); - - context.clip(); - - // Compute matrix transform - var delta = (u0 * v1) + (v0 * u2) + (u1 * v2) - (v1 * u2) - (v0 * u1) - (u0 * v2); - var deltaA = (x0 * v1) + (v0 * x2) + (x1 * v2) - (v1 * x2) - (v0 * x1) - (x0 * v2); - var deltaB = (u0 * x1) + (x0 * u2) + (u1 * x2) - (x1 * u2) - (x0 * u1) - (u0 * x2); - var deltaC = (u0 * v1 * x2) + (v0 * x1 * u2) + (x0 * u1 * v2) - (x0 * v1 * u2) - (v0 * u1 * x2) - (u0 * x1 * v2); - var deltaD = (y0 * v1) + (v0 * y2) + (y1 * v2) - (v1 * y2) - (v0 * y1) - (y0 * v2); - var deltaE = (u0 * y1) + (y0 * u2) + (u1 * y2) - (y1 * u2) - (y0 * u1) - (u0 * y2); - var deltaF = (u0 * v1 * y2) + (v0 * y1 * u2) + (y0 * u1 * v2) - (y0 * v1 * u2) - (v0 * u1 * y2) - (u0 * y1 * v2); - - context.transform(deltaA / delta, deltaD / delta, - deltaB / delta, deltaE / delta, - deltaC / delta, deltaF / delta); - - context.drawImage(textureSource, 0, 0); - context.restore(); -}; - - - -/** - * Renders a flat Mesh - * - * @param Mesh {Mesh} The Mesh to render - * @private - */ -Mesh.prototype.renderMeshFlat = function (Mesh) -{ - var context = this.context; - var vertices = Mesh.vertices; - - var length = vertices.length/2; - // this.count++; - - context.beginPath(); - for (var i=1; i < length-2; i++) - { - // draw some triangles! - var index = i*2; - - var x0 = vertices[index], x1 = vertices[index+2], x2 = vertices[index+4]; - var y0 = vertices[index+1], y1 = vertices[index+3], y2 = vertices[index+5]; - - context.moveTo(x0, y0); - context.lineTo(x1, y1); - context.lineTo(x2, y2); - } - - context.fillStyle = '#FF0000'; - context.fill(); - context.closePath(); -}; - -/* -Mesh.prototype.setTexture = function (texture) -{ - //TODO SET THE TEXTURES - //TODO VISIBILITY - //TODO SETTER - - // stop current texture - this.texture = texture; - this.width = texture.frame.width; - this.height = texture.frame.height; - this.updateFrame = true; -}; - */ - -/** - * When the texture is updated, this event will fire to update the scale and frame - * - * @param event - * @private - */ - -Mesh.prototype.onTextureUpdate = function () -{ - this.updateFrame = true; -}; - -/** - * Returns the bounds of the mesh as a rectangle. The bounds calculation takes the worldTransform into account. - * - * @param matrix {Matrix} the transformation matrix of the sprite - * @return {Rectangle} the framing rectangle - */ -Mesh.prototype.getBounds = function (matrix) -{ - var worldTransform = matrix || this.worldTransform; - - var a = worldTransform.a; - var b = worldTransform.b; - var c = worldTransform.c; - var d = worldTransform.d; - var tx = worldTransform.tx; - var ty = worldTransform.ty; - - var maxX = -Infinity; - var maxY = -Infinity; - - var minX = Infinity; - var minY = Infinity; - - var vertices = this.vertices; - for (var i = 0, n = vertices.length; i < n; i += 2) - { - var rawX = vertices[i], rawY = vertices[i + 1]; - var x = (a * rawX) + (c * rawY) + tx; - var y = (d * rawY) + (b * rawX) + ty; - - minX = x < minX ? x : minX; - minY = y < minY ? y : minY; - - maxX = x > maxX ? x : maxX; - maxY = y > maxY ? y : maxY; - } - - if (minX === -Infinity || maxY === Infinity) - { - return core.math.Rectangle.EMPTY; - } - - var bounds = this._bounds; - - bounds.x = minX; - bounds.width = maxX - minX; - - bounds.y = minY; - bounds.height = maxY - minY; - - // store a reference so that if this function gets called again in the render cycle we do not have to recalculate - this._currentBounds = bounds; - - return bounds; -}; - -/** - * Different drawing buffer modes supported - * - * @static - * @constant - * @property {object} DRAW_MODES - * @property {number} DRAW_MODES.TRIANGLE_MESH - * @property {number} DRAW_MODES.TRIANGLES - */ -Mesh.DRAW_MODES = { - TRIANGLE_MESH: 0, - TRIANGLES: 1 -}; diff --git a/src/extras/mesh/Rope.js b/src/extras/mesh/Rope.js deleted file mode 100644 index 8119995..0000000 --- a/src/extras/mesh/Rope.js +++ /dev/null @@ -1,192 +0,0 @@ -var Mesh = require('./Mesh'); - -/** - * The rope allows you to draw a texture across several points and them manipulate these points - * - *```js - * for (var i = 0; i < 20; i++) { - * points.push(new PIXI.Point(i * 50, 0)); - * }; - * var rope = new PIXI.Rope(PIXI.Texture.fromImage("snake.png"), points); - * ``` - * - * @class - * @extends Mesh - * @memberof PIXI.extras - * @param {Texture} texture - The texture to use on the rope. - * @param {Array} points - An array of {Point} objects to construct this rope. - * - */ -function Rope(texture, points) -{ - Mesh.call(this, texture); - - /* - * @member {Array} An array of points that determine the rope - */ - this.points = points; - - /* - * @member {Float32Array} An array of vertices used to construct this rope. - */ - this.vertices = new Float32Array(points.length * 4); - - /* - * @member {Float32Array} The WebGL Uvs of the rope. - */ - this.uvs = new Float32Array(points.length * 4); - - /* - * @member {Float32Array} An array containing the color components - */ - this.colors = new Float32Array(points.length * 2); - - /* - * @member {Uint16Array} An array containing the indices of the vertices - */ - this.indices = new Uint16Array(points.length * 2); - - this.refresh(); -} - - -// constructor -Rope.prototype = Object.create(Mesh.prototype); -Rope.prototype.constructor = Rope; -module.exports = Rope; - -/** - * Refreshes - * - */ -Rope.prototype.refresh = function () -{ - var points = this.points; - - if (points.length < 1) - { - return; - } - - var uvs = this.uvs; - - var indices = this.indices; - var colors = this.colors; - - // this.count -= 0.2; - - uvs[0] = 0; - uvs[1] = 0; - uvs[2] = 0; - uvs[3] = 1; - - colors[0] = 1; - colors[1] = 1; - - indices[0] = 0; - indices[1] = 1; - - var total = points.length, - point, index, amount; - - for (var i = 1; i < total; i++) - { - point = points[i]; - index = i * 4; - // time to do some smart drawing! - amount = i / (total-1); - - if (i%2) - { - uvs[index] = amount; - uvs[index+1] = 0; - - uvs[index+2] = amount; - uvs[index+3] = 1; - } - else - { - uvs[index] = amount; - uvs[index+1] = 0; - - uvs[index+2] = amount; - uvs[index+3] = 1; - } - - index = i * 2; - colors[index] = 1; - colors[index+1] = 1; - - index = i * 2; - indices[index] = index; - indices[index + 1] = index + 1; - } -}; - -/* - * Updates the object transform for rendering - * - * @private - */ -Rope.prototype.updateTransform = function () -{ - var points = this.points; - - if (points.length < 1) - { - return; - } - - var lastPoint = points[0]; - var nextPoint; - var perpX = 0; - var perpY = 0; - - // this.count -= 0.2; - - var vertices = this.vertices; - var total = points.length, - point, index, ratio, perpLength, num; - - for (var i = 0; i < total; i++) - { - point = points[i]; - index = i * 4; - - if (i < points.length-1) - { - nextPoint = points[i+1]; - } - else - { - nextPoint = point; - } - - perpY = -(nextPoint.x - lastPoint.x); - perpX = nextPoint.y - lastPoint.y; - - ratio = (1 - (i / (total-1))) * 10; - - if (ratio > 1) - { - ratio = 1; - } - - perpLength = Math.sqrt(perpX * perpX + perpY * perpY); - num = this.texture.height / 2; //(20 + Math.abs(Math.sin((i + this.count) * 0.3) * 50) )* ratio; - perpX /= perpLength; - perpY /= perpLength; - - perpX *= num; - perpY *= num; - - vertices[index] = point.x + perpX; - vertices[index+1] = point.y + perpY; - vertices[index+2] = point.x - perpX; - vertices[index+3] = point.y - perpY; - - lastPoint = point; - } - - this.containerUpdateTransform(); -}; diff --git a/src/extras/mesh/index.js b/src/extras/mesh/index.js deleted file mode 100644 index dd37f87..0000000 --- a/src/extras/mesh/index.js +++ /dev/null @@ -1,16 +0,0 @@ -/** - * @file Main export of the PIXI extras library - * @author Mat Groves - * @copyright 2013-2015 GoodBoyDigital - * @license {@link https://github.com/GoodBoyDigital/pixi.js/blob/master/LICENSE|MIT License} - */ - -/** - * @namespace PIXI.extras - */ -module.exports = { - Mesh: require('./Mesh'), - Rope: require('./Rope'), - MeshRenderer: require('./webgl/MeshRenderer'), - MeshShader: require('./webgl/MeshShader') -}; diff --git a/src/extras/mesh/webgl/MeshRenderer.js b/src/extras/mesh/webgl/MeshRenderer.js deleted file mode 100644 index 2dd7678..0000000 --- a/src/extras/mesh/webgl/MeshRenderer.js +++ /dev/null @@ -1,215 +0,0 @@ -var ObjectRenderer = require('../../../core/renderers/webgl/utils/ObjectRenderer'), - WebGLRenderer = require('../../../core/renderers/webgl/WebGLRenderer'); - -/** - * @author Mat Groves - * - * Big thanks to the very clever Matt DesLauriers https://github.com/mattdesl/ - * for creating the original pixi version! - * Also a thanks to https://github.com/bchevalier for tweaking the tint and alpha so that they now share 4 bytes on the vertex buffer - * - * Heavily inspired by LibGDX's MeshRenderer: - * https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/graphics/g2d/MeshRenderer.java - */ - -/** - * - * @class - * @private - * @memberof PIXI - * @extends ObjectRenderer - * @param renderer {WebGLRenderer} The renderer this sprite batch works for. - */ -function MeshRenderer(renderer) -{ - ObjectRenderer.call(this, renderer); - - - /** - * Holds the indices - * - * @member {Uint16Array} - */ - this.indices = new Uint16Array(15000); - - //TODO this could be a single buffer shared amongst all renderers as we reuse this set up in most renderers - for (var i=0, j=0; i < 15000; i += 6, j += 4) - { - this.indices[i + 0] = j + 0; - this.indices[i + 1] = j + 1; - this.indices[i + 2] = j + 2; - this.indices[i + 3] = j + 0; - this.indices[i + 4] = j + 2; - this.indices[i + 5] = j + 3; - } -} - -MeshRenderer.prototype = Object.create(ObjectRenderer.prototype); -MeshRenderer.prototype.constructor = MeshRenderer; -module.exports = MeshRenderer; - -WebGLRenderer.registerPlugin('mesh', MeshRenderer); - -/** - * Sets up the renderer context and necessary buffers. - * - * @private - * @param gl {WebGLRenderingContext} the current WebGL drawing context - */ -MeshRenderer.prototype.onContextChange = function () -{ - -}; - -/** - * Renders the sprite object. - * - * @param mesh {Mesh} the mesh to render - */ -MeshRenderer.prototype.render = function (mesh) -{ -// return; - if(!mesh._vertexBuffer) - { - this._initWebGL(mesh); - } - - var renderer = this.renderer, - gl = renderer.gl, - texture = mesh.texture.baseTexture, - shader = renderer.shaderManager.plugins.meshShader; - -// var drawMode = mesh.drawMode === Strip.DRAW_MODES.TRIANGLE_STRIP ? gl.TRIANGLE_STRIP : gl.TRIANGLES; - var drawMode = gl.TRIANGLE_STRIP; - - renderer.blendModeManager.setBlendMode(mesh.blendMode); - - - // set uniforms - gl.uniformMatrix3fv(shader.uniforms.translationMatrix._location, false, mesh.worldTransform.toArray(true)); - - gl.uniformMatrix3fv(shader.uniforms.projectionMatrix._location, false, renderer.currentRenderTarget.projectionMatrix.toArray(true)); - gl.uniform1f(shader.uniforms.alpha._location, mesh.worldAlpha); - - if (!mesh.dirty) - { - - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._vertexBuffer); - gl.bufferSubData(gl.ARRAY_BUFFER, 0, mesh.vertices); - gl.vertexAttribPointer(shader.attributes.aVertexPosition, 2, gl.FLOAT, false, 0, 0); - - - // update the uvs - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._uvBuffer); - gl.vertexAttribPointer(shader.attributes.aTextureCoord, 2, gl.FLOAT, false, 0, 0); - - - gl.activeTexture(gl.TEXTURE0); - - if (!texture._glTextures[gl.id]) - { - this.renderer.updateTexture(texture); - } - else - { - // bind the current texture - gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]); - } - } - else - { - - mesh.dirty = false; - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER, mesh.vertices, gl.STATIC_DRAW); - gl.vertexAttribPointer(shader.attributes.aVertexPosition, 2, gl.FLOAT, false, 0, 0); - - // update the uvs - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._uvBuffer); - gl.bufferData(gl.ARRAY_BUFFER, mesh.uvs, gl.STATIC_DRAW); - gl.vertexAttribPointer(shader.attributes.aTextureCoord, 2, gl.FLOAT, false, 0, 0); - - gl.activeTexture(gl.TEXTURE0); - - if (!texture._glTextures[gl.id]) - { - this.renderer.updateTexture(texture); - } - else - { - // bind the current texture - gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]); - } - - // dont need to upload! - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, mesh._indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, mesh.indices, gl.STATIC_DRAW); - - } - - gl.drawElements(drawMode, mesh.indices.length, gl.UNSIGNED_SHORT, 0); - -}; - -/** - * Prepares all the buffers to render this mesh - * @param mesh {Mesh} the mesh to render - */ -MeshRenderer.prototype._initWebGL = function (mesh) -{ - // build the strip! - var gl = this.renderer.gl; - - mesh._vertexBuffer = gl.createBuffer(); - mesh._indexBuffer = gl.createBuffer(); - mesh._uvBuffer = gl.createBuffer(); - mesh._colorBuffer = gl.createBuffer(); - - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER, mesh.vertices, gl.DYNAMIC_DRAW); - - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._uvBuffer); - gl.bufferData(gl.ARRAY_BUFFER, mesh.uvs, gl.STATIC_DRAW); - - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._colorBuffer); - gl.bufferData(gl.ARRAY_BUFFER, mesh.colors, gl.STATIC_DRAW); - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, mesh._indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, mesh.indices, gl.STATIC_DRAW); -}; - - -/** - * Empties the current batch. - * - */ -MeshRenderer.prototype.flush = function () -{ - -}; - -/** - * Starts a new mesh renderer. - * - */ -MeshRenderer.prototype.start = function () -{ - var gl = this.renderer.gl, - shader = this.renderer.shaderManager.plugins.meshShader; - - this.renderer.shaderManager.setShader(shader); - - // dont need to upload! - //gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indices); - - - // this.s -}; - -/** - * Destroys the Mesh renderer - * - */ -MeshRenderer.prototype.destroy = function () -{ -}; diff --git a/src/extras/mesh/webgl/MeshShader.js b/src/extras/mesh/webgl/MeshShader.js deleted file mode 100644 index 51c03f5..0000000 --- a/src/extras/mesh/webgl/MeshShader.js +++ /dev/null @@ -1,59 +0,0 @@ -var core = require('../../../core'); - -/** - * @class - * @extends Shader - * @memberof PIXI.extras - * @param shaderManager {ShaderManager} The WebGL shader manager this shader works for. - */ -function StripShader(shaderManager) -{ - core.Shader.call(this, - shaderManager, - // vertex shader - [ - 'precision lowp float;', - 'attribute vec2 aVertexPosition;', - 'attribute vec2 aTextureCoord;', - - 'uniform mat3 translationMatrix;', - 'uniform mat3 projectionMatrix;', - - 'varying vec2 vTextureCoord;', - - 'void main(void){', - ' gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);', - ' vTextureCoord = aTextureCoord;', - '}' - ].join('\n'), - [ - 'precision lowp float;', - - 'varying vec2 vTextureCoord;', - 'uniform float alpha;', - - 'uniform sampler2D uSampler;', - - 'void main(void){', - ' gl_FragColor = texture2D(uSampler, vTextureCoord) * alpha ;', - '}' - ].join('\n'), - // custom uniforms - { - alpha: { type: '1f', value: 0 }, - translationMatrix: { type: 'mat3', value: new Float32Array(9) }, - projectionMatrix: { type: 'mat3', value: new Float32Array(9) } - }, - // custom attributes - { - aVertexPosition:0, - aTextureCoord:0 - } - ); -} - -StripShader.prototype = Object.create(core.Shader.prototype); -StripShader.prototype.constructor = StripShader; -module.exports = StripShader; - -core.ShaderManager.registerPlugin('meshShader', StripShader); diff --git a/src/index.js b/src/index.js index 2c1f999..da8c001 100644 --- a/src/index.js +++ b/src/index.js @@ -1,6 +1,7 @@ var core = require('./core'); extendCore(require('./extras')); +extendCore(require('./mesh')); extendCore(require('./filters')); extendCore(require('./interaction')); extendCore(require('./loaders')); diff --git a/src/mesh/Mesh.js b/src/mesh/Mesh.js new file mode 100644 index 0000000..c006078 --- /dev/null +++ b/src/mesh/Mesh.js @@ -0,0 +1,387 @@ +var core = require('../core'); + +/** + * Base mesh class + * @class + * @extends Container + * @memberof PIXI.extras + * @param texture {Texture} The texture to use + * @param [vertices] {Float32Arrif you want to specify the vertices + * @param [uvs] {Float32Array} if you want to specify the uvs + * @param [indices] {Uint16Array} if you want to specify the indices + * @param [drawMode] {number} the drawMode, can be any of the Mesh.DRAW_MODES consts + */ +function Mesh(texture, vertices, uvs, indices, drawMode) +{ + core.Container.call(this); + + /** + * The texture of the Mesh + * + * @member {Texture} + */ + this.texture = texture; + + /** + * The Uvs of the Mesh + * + * @member {Float32Array} + */ + this.uvs = uvs || new Float32Array([0, 1, + 1, 1, + 1, 0, + 0, 1]); + + /** + * An array of vertices + * + * @member {Float32Array} + */ + this.vertices = vertices || new Float32Array([0, 0, + 100, 0, + 100, 100, + 0, 100]); + + /* + * @member {Uint16Array} An array containing the indices of the vertices + */ + // TODO auto generate this based on draw mode! + this.indices = indices || new Uint16Array([0, 1, 2, 3]); + + /** + * Whether the Mesh is dirty or not + * + * @member {boolean} + */ + this.dirty = true; + + /** + * The blend mode to be applied to the sprite. Set to blendModes.NORMAL to remove any blend mode. + * + * @member {number} + * @default CONST.BLEND_MODES.NORMAL; + */ + this.blendMode = core.CONST.BLEND_MODES.NORMAL; + + /** + * Triangles in canvas mode are automatically antialiased, use this value to force triangles to overlap a bit with each other. + * + * @member {number}= + */ + this.canvasPadding = 0; + + /** + * The way the Mesh should be drawn, can be any of the Mesh.DRAW_MODES consts + * + * @member {number} + */ + this.drawMode = drawMode || Mesh.DRAW_MODES.TRIANGLE_MESH; +} + +// constructor +Mesh.prototype = Object.create(core.Container.prototype); +Mesh.prototype.constructor = Mesh; +module.exports = Mesh; + +/** + * Renders the object using the WebGL renderer + * + * @param renderer {WebGLRenderer} a reference to the WebGL renderer + */ +Mesh.prototype._renderWebGL = function (renderer) +{ + renderer.setObjectRenderer(renderer.plugins.mesh); + renderer.plugins.mesh.render(this); +}; + +/** + * Renders the object using the Canvas renderer + * + * @param renderer {CanvasRenderer} + */ +Mesh.prototype._renderCanvas = function (renderer) +{ + var context = renderer.context; + + var transform = this.worldTransform; + + if (renderer.roundPixels) + { + context.setTransform(transform.a, transform.b, transform.c, transform.d, transform.tx | 0, transform.ty | 0); + } + else + { + context.setTransform(transform.a, transform.b, transform.c, transform.d, transform.tx, transform.ty); + } + + if (this.drawMode === Mesh.DRAW_MODES.TRIANGLE_MESH) + { + this._renderCanvasTriangleMesh(context); + } + else + { + this._renderCanvasTriangles(context); + } +}; + +/** + * Draws the object in Triangle Mesh mode using canvas + * + * @param context {CanvasRenderingContext2D} the current drawing context + * @private + */ +Mesh.prototype._renderCanvasTriangleMesh = function (context) +{ + // draw triangles!! + var vertices = this.vertices; + var uvs = this.uvs; + + var length = vertices.length / 2; + // this.count++; + + for (var i = 0; i < length - 2; i++) + { + // draw some triangles! + var index = i * 2; + this._renderCanvasDrawTriangle(context, vertices, uvs, index, (index + 2), (index + 4)); + } +}; + +/** + * Draws the object in triangle mode using canvas + * + * @param context {CanvasRenderingContext2D} the current drawing context + * @private + */ +Mesh.prototype._renderCanvasTriangles = function (context) +{ + // draw triangles!! + var vertices = this.vertices; + var uvs = this.uvs; + var indices = this.indices; + + var length = indices.length; + // this.count++; + + for (var i = 0; i < length; i += 3) + { + // draw some triangles! + var index0 = indices[i] * 2, index1 = indices[i + 1] * 2, index2 = indices[i + 2] * 2; + this._renderCanvasDrawTriangle(context, vertices, uvs, index0, index1, index2); + } +}; + +/** + * Draws one of the triangles that form this Mesh + * + * @param context {CanvasRenderingContext2D} the current drawing context + * @param vertices {Float32Array} a reference to the vertices of the Mesh + * @param uvs {Float32Array} a reference to the uvs of the Mesh + * @param index0 {number} the index of the first vertex + * @param index1 {number} the index of the second vertex + * @param index2 {number} the index of the third vertex + * @private + */ +Mesh.prototype._renderCanvasDrawTriangle = function (context, vertices, uvs, index0, index1, index2) +{ + var textureSource = this.texture.baseTexture.source; + var textureWidth = this.texture.width; + var textureHeight = this.texture.height; + + var x0 = vertices[index0], x1 = vertices[index1], x2 = vertices[index2]; + var y0 = vertices[index0 + 1], y1 = vertices[index1 + 1], y2 = vertices[index2 + 1]; + + var u0 = uvs[index0] * textureWidth, u1 = uvs[index1] * textureWidth, u2 = uvs[index2] * textureWidth; + var v0 = uvs[index0 + 1] * textureHeight, v1 = uvs[index1 + 1] * textureHeight, v2 = uvs[index2 + 1] * textureHeight; + + if (this.canvasPadding > 0) + { + var paddingX = this.canvasPadding / this.worldTransform.a; + var paddingY = this.canvasPadding / this.worldTransform.d; + var centerX = (x0 + x1 + x2) / 3; + var centerY = (y0 + y1 + y2) / 3; + + var normX = x0 - centerX; + var normY = y0 - centerY; + + var dist = Math.sqrt(normX * normX + normY * normY); + x0 = centerX + (normX / dist) * (dist + paddingX); + y0 = centerY + (normY / dist) * (dist + paddingY); + + // + + normX = x1 - centerX; + normY = y1 - centerY; + + dist = Math.sqrt(normX * normX + normY * normY); + x1 = centerX + (normX / dist) * (dist + paddingX); + y1 = centerY + (normY / dist) * (dist + paddingY); + + normX = x2 - centerX; + normY = y2 - centerY; + + dist = Math.sqrt(normX * normX + normY * normY); + x2 = centerX + (normX / dist) * (dist + paddingX); + y2 = centerY + (normY / dist) * (dist + paddingY); + } + + context.save(); + context.beginPath(); + + + context.moveTo(x0, y0); + context.lineTo(x1, y1); + context.lineTo(x2, y2); + + context.closePath(); + + context.clip(); + + // Compute matrix transform + var delta = (u0 * v1) + (v0 * u2) + (u1 * v2) - (v1 * u2) - (v0 * u1) - (u0 * v2); + var deltaA = (x0 * v1) + (v0 * x2) + (x1 * v2) - (v1 * x2) - (v0 * x1) - (x0 * v2); + var deltaB = (u0 * x1) + (x0 * u2) + (u1 * x2) - (x1 * u2) - (x0 * u1) - (u0 * x2); + var deltaC = (u0 * v1 * x2) + (v0 * x1 * u2) + (x0 * u1 * v2) - (x0 * v1 * u2) - (v0 * u1 * x2) - (u0 * x1 * v2); + var deltaD = (y0 * v1) + (v0 * y2) + (y1 * v2) - (v1 * y2) - (v0 * y1) - (y0 * v2); + var deltaE = (u0 * y1) + (y0 * u2) + (u1 * y2) - (y1 * u2) - (y0 * u1) - (u0 * y2); + var deltaF = (u0 * v1 * y2) + (v0 * y1 * u2) + (y0 * u1 * v2) - (y0 * v1 * u2) - (v0 * u1 * y2) - (u0 * y1 * v2); + + context.transform(deltaA / delta, deltaD / delta, + deltaB / delta, deltaE / delta, + deltaC / delta, deltaF / delta); + + context.drawImage(textureSource, 0, 0); + context.restore(); +}; + + + +/** + * Renders a flat Mesh + * + * @param Mesh {Mesh} The Mesh to render + * @private + */ +Mesh.prototype.renderMeshFlat = function (Mesh) +{ + var context = this.context; + var vertices = Mesh.vertices; + + var length = vertices.length/2; + // this.count++; + + context.beginPath(); + for (var i=1; i < length-2; i++) + { + // draw some triangles! + var index = i*2; + + var x0 = vertices[index], x1 = vertices[index+2], x2 = vertices[index+4]; + var y0 = vertices[index+1], y1 = vertices[index+3], y2 = vertices[index+5]; + + context.moveTo(x0, y0); + context.lineTo(x1, y1); + context.lineTo(x2, y2); + } + + context.fillStyle = '#FF0000'; + context.fill(); + context.closePath(); +}; + +/* +Mesh.prototype.setTexture = function (texture) +{ + //TODO SET THE TEXTURES + //TODO VISIBILITY + //TODO SETTER + + // stop current texture + this.texture = texture; + this.width = texture.frame.width; + this.height = texture.frame.height; + this.updateFrame = true; +}; + */ + +/** + * When the texture is updated, this event will fire to update the scale and frame + * + * @param event + * @private + */ + +Mesh.prototype.onTextureUpdate = function () +{ + this.updateFrame = true; +}; + +/** + * Returns the bounds of the mesh as a rectangle. The bounds calculation takes the worldTransform into account. + * + * @param matrix {Matrix} the transformation matrix of the sprite + * @return {Rectangle} the framing rectangle + */ +Mesh.prototype.getBounds = function (matrix) +{ + var worldTransform = matrix || this.worldTransform; + + var a = worldTransform.a; + var b = worldTransform.b; + var c = worldTransform.c; + var d = worldTransform.d; + var tx = worldTransform.tx; + var ty = worldTransform.ty; + + var maxX = -Infinity; + var maxY = -Infinity; + + var minX = Infinity; + var minY = Infinity; + + var vertices = this.vertices; + for (var i = 0, n = vertices.length; i < n; i += 2) + { + var rawX = vertices[i], rawY = vertices[i + 1]; + var x = (a * rawX) + (c * rawY) + tx; + var y = (d * rawY) + (b * rawX) + ty; + + minX = x < minX ? x : minX; + minY = y < minY ? y : minY; + + maxX = x > maxX ? x : maxX; + maxY = y > maxY ? y : maxY; + } + + if (minX === -Infinity || maxY === Infinity) + { + return core.math.Rectangle.EMPTY; + } + + var bounds = this._bounds; + + bounds.x = minX; + bounds.width = maxX - minX; + + bounds.y = minY; + bounds.height = maxY - minY; + + // store a reference so that if this function gets called again in the render cycle we do not have to recalculate + this._currentBounds = bounds; + + return bounds; +}; + +/** + * Different drawing buffer modes supported + * + * @static + * @constant + * @property {object} DRAW_MODES + * @property {number} DRAW_MODES.TRIANGLE_MESH + * @property {number} DRAW_MODES.TRIANGLES + */ +Mesh.DRAW_MODES = { + TRIANGLE_MESH: 0, + TRIANGLES: 1 +}; diff --git a/src/mesh/Rope.js b/src/mesh/Rope.js new file mode 100644 index 0000000..8119995 --- /dev/null +++ b/src/mesh/Rope.js @@ -0,0 +1,192 @@ +var Mesh = require('./Mesh'); + +/** + * The rope allows you to draw a texture across several points and them manipulate these points + * + *```js + * for (var i = 0; i < 20; i++) { + * points.push(new PIXI.Point(i * 50, 0)); + * }; + * var rope = new PIXI.Rope(PIXI.Texture.fromImage("snake.png"), points); + * ``` + * + * @class + * @extends Mesh + * @memberof PIXI.extras + * @param {Texture} texture - The texture to use on the rope. + * @param {Array} points - An array of {Point} objects to construct this rope. + * + */ +function Rope(texture, points) +{ + Mesh.call(this, texture); + + /* + * @member {Array} An array of points that determine the rope + */ + this.points = points; + + /* + * @member {Float32Array} An array of vertices used to construct this rope. + */ + this.vertices = new Float32Array(points.length * 4); + + /* + * @member {Float32Array} The WebGL Uvs of the rope. + */ + this.uvs = new Float32Array(points.length * 4); + + /* + * @member {Float32Array} An array containing the color components + */ + this.colors = new Float32Array(points.length * 2); + + /* + * @member {Uint16Array} An array containing the indices of the vertices + */ + this.indices = new Uint16Array(points.length * 2); + + this.refresh(); +} + + +// constructor +Rope.prototype = Object.create(Mesh.prototype); +Rope.prototype.constructor = Rope; +module.exports = Rope; + +/** + * Refreshes + * + */ +Rope.prototype.refresh = function () +{ + var points = this.points; + + if (points.length < 1) + { + return; + } + + var uvs = this.uvs; + + var indices = this.indices; + var colors = this.colors; + + // this.count -= 0.2; + + uvs[0] = 0; + uvs[1] = 0; + uvs[2] = 0; + uvs[3] = 1; + + colors[0] = 1; + colors[1] = 1; + + indices[0] = 0; + indices[1] = 1; + + var total = points.length, + point, index, amount; + + for (var i = 1; i < total; i++) + { + point = points[i]; + index = i * 4; + // time to do some smart drawing! + amount = i / (total-1); + + if (i%2) + { + uvs[index] = amount; + uvs[index+1] = 0; + + uvs[index+2] = amount; + uvs[index+3] = 1; + } + else + { + uvs[index] = amount; + uvs[index+1] = 0; + + uvs[index+2] = amount; + uvs[index+3] = 1; + } + + index = i * 2; + colors[index] = 1; + colors[index+1] = 1; + + index = i * 2; + indices[index] = index; + indices[index + 1] = index + 1; + } +}; + +/* + * Updates the object transform for rendering + * + * @private + */ +Rope.prototype.updateTransform = function () +{ + var points = this.points; + + if (points.length < 1) + { + return; + } + + var lastPoint = points[0]; + var nextPoint; + var perpX = 0; + var perpY = 0; + + // this.count -= 0.2; + + var vertices = this.vertices; + var total = points.length, + point, index, ratio, perpLength, num; + + for (var i = 0; i < total; i++) + { + point = points[i]; + index = i * 4; + + if (i < points.length-1) + { + nextPoint = points[i+1]; + } + else + { + nextPoint = point; + } + + perpY = -(nextPoint.x - lastPoint.x); + perpX = nextPoint.y - lastPoint.y; + + ratio = (1 - (i / (total-1))) * 10; + + if (ratio > 1) + { + ratio = 1; + } + + perpLength = Math.sqrt(perpX * perpX + perpY * perpY); + num = this.texture.height / 2; //(20 + Math.abs(Math.sin((i + this.count) * 0.3) * 50) )* ratio; + perpX /= perpLength; + perpY /= perpLength; + + perpX *= num; + perpY *= num; + + vertices[index] = point.x + perpX; + vertices[index+1] = point.y + perpY; + vertices[index+2] = point.x - perpX; + vertices[index+3] = point.y - perpY; + + lastPoint = point; + } + + this.containerUpdateTransform(); +}; diff --git a/src/mesh/index.js b/src/mesh/index.js new file mode 100644 index 0000000..dd37f87 --- /dev/null +++ b/src/mesh/index.js @@ -0,0 +1,16 @@ +/** + * @file Main export of the PIXI extras library + * @author Mat Groves + * @copyright 2013-2015 GoodBoyDigital + * @license {@link https://github.com/GoodBoyDigital/pixi.js/blob/master/LICENSE|MIT License} + */ + +/** + * @namespace PIXI.extras + */ +module.exports = { + Mesh: require('./Mesh'), + Rope: require('./Rope'), + MeshRenderer: require('./webgl/MeshRenderer'), + MeshShader: require('./webgl/MeshShader') +}; diff --git a/src/extras/index.js b/src/extras/index.js index 267e97c..6f14e0d 100644 --- a/src/extras/index.js +++ b/src/extras/index.js @@ -11,7 +11,6 @@ module.exports = { MovieClip: require('./MovieClip'), TilingSprite: require('./TilingSprite'), - mesh: require('./mesh/index'), cacheAsBitmap: require('./cacheAsBitmap'), getChildByName: require('./getChildByName') }; diff --git a/src/extras/mesh/Mesh.js b/src/extras/mesh/Mesh.js deleted file mode 100644 index 30431ae..0000000 --- a/src/extras/mesh/Mesh.js +++ /dev/null @@ -1,387 +0,0 @@ -var core = require('../../core'); - -/** - * Base mesh class - * @class - * @extends Container - * @memberof PIXI.extras - * @param texture {Texture} The texture to use - * @param [vertices] {Float32Arrif you want to specify the vertices - * @param [uvs] {Float32Array} if you want to specify the uvs - * @param [indices] {Uint16Array} if you want to specify the indices - * @param [drawMode] {number} the drawMode, can be any of the Mesh.DRAW_MODES consts - */ -function Mesh(texture, vertices, uvs, indices, drawMode) -{ - core.Container.call(this); - - /** - * The texture of the Mesh - * - * @member {Texture} - */ - this.texture = texture; - - /** - * The Uvs of the Mesh - * - * @member {Float32Array} - */ - this.uvs = uvs || new Float32Array([0, 1, - 1, 1, - 1, 0, - 0, 1]); - - /** - * An array of vertices - * - * @member {Float32Array} - */ - this.vertices = vertices || new Float32Array([0, 0, - 100, 0, - 100, 100, - 0, 100]); - - /* - * @member {Uint16Array} An array containing the indices of the vertices - */ - // TODO auto generate this based on draw mode! - this.indices = indices || new Uint16Array([0, 1, 2, 3]); - - /** - * Whether the Mesh is dirty or not - * - * @member {boolean} - */ - this.dirty = true; - - /** - * The blend mode to be applied to the sprite. Set to blendModes.NORMAL to remove any blend mode. - * - * @member {number} - * @default CONST.BLEND_MODES.NORMAL; - */ - this.blendMode = core.CONST.BLEND_MODES.NORMAL; - - /** - * Triangles in canvas mode are automatically antialiased, use this value to force triangles to overlap a bit with each other. - * - * @member {number}= - */ - this.canvasPadding = 0; - - /** - * The way the Mesh should be drawn, can be any of the Mesh.DRAW_MODES consts - * - * @member {number} - */ - this.drawMode = drawMode || Mesh.DRAW_MODES.TRIANGLE_MESH; -} - -// constructor -Mesh.prototype = Object.create(core.Container.prototype); -Mesh.prototype.constructor = Mesh; -module.exports = Mesh; - -/** - * Renders the object using the WebGL renderer - * - * @param renderer {WebGLRenderer} a reference to the WebGL renderer - */ -Mesh.prototype._renderWebGL = function (renderer) -{ - renderer.setObjectRenderer(renderer.plugins.mesh); - renderer.plugins.mesh.render(this); -}; - -/** - * Renders the object using the Canvas renderer - * - * @param renderer {CanvasRenderer} - */ -Mesh.prototype._renderCanvas = function (renderer) -{ - var context = renderer.context; - - var transform = this.worldTransform; - - if (renderer.roundPixels) - { - context.setTransform(transform.a, transform.b, transform.c, transform.d, transform.tx | 0, transform.ty | 0); - } - else - { - context.setTransform(transform.a, transform.b, transform.c, transform.d, transform.tx, transform.ty); - } - - if (this.drawMode === Mesh.DRAW_MODES.TRIANGLE_MESH) - { - this._renderCanvasTriangleMesh(context); - } - else - { - this._renderCanvasTriangles(context); - } -}; - -/** - * Draws the object in Triangle Mesh mode using canvas - * - * @param context {CanvasRenderingContext2D} the current drawing context - * @private - */ -Mesh.prototype._renderCanvasTriangleMesh = function (context) -{ - // draw triangles!! - var vertices = this.vertices; - var uvs = this.uvs; - - var length = vertices.length / 2; - // this.count++; - - for (var i = 0; i < length - 2; i++) - { - // draw some triangles! - var index = i * 2; - this._renderCanvasDrawTriangle(context, vertices, uvs, index, (index + 2), (index + 4)); - } -}; - -/** - * Draws the object in triangle mode using canvas - * - * @param context {CanvasRenderingContext2D} the current drawing context - * @private - */ -Mesh.prototype._renderCanvasTriangles = function (context) -{ - // draw triangles!! - var vertices = this.vertices; - var uvs = this.uvs; - var indices = this.indices; - - var length = indices.length; - // this.count++; - - for (var i = 0; i < length; i += 3) - { - // draw some triangles! - var index0 = indices[i] * 2, index1 = indices[i + 1] * 2, index2 = indices[i + 2] * 2; - this._renderCanvasDrawTriangle(context, vertices, uvs, index0, index1, index2); - } -}; - -/** - * Draws one of the triangles that form this Mesh - * - * @param context {CanvasRenderingContext2D} the current drawing context - * @param vertices {Float32Array} a reference to the vertices of the Mesh - * @param uvs {Float32Array} a reference to the uvs of the Mesh - * @param index0 {number} the index of the first vertex - * @param index1 {number} the index of the second vertex - * @param index2 {number} the index of the third vertex - * @private - */ -Mesh.prototype._renderCanvasDrawTriangle = function (context, vertices, uvs, index0, index1, index2) -{ - var textureSource = this.texture.baseTexture.source; - var textureWidth = this.texture.width; - var textureHeight = this.texture.height; - - var x0 = vertices[index0], x1 = vertices[index1], x2 = vertices[index2]; - var y0 = vertices[index0 + 1], y1 = vertices[index1 + 1], y2 = vertices[index2 + 1]; - - var u0 = uvs[index0] * textureWidth, u1 = uvs[index1] * textureWidth, u2 = uvs[index2] * textureWidth; - var v0 = uvs[index0 + 1] * textureHeight, v1 = uvs[index1 + 1] * textureHeight, v2 = uvs[index2 + 1] * textureHeight; - - if (this.canvasPadding > 0) - { - var paddingX = this.canvasPadding / this.worldTransform.a; - var paddingY = this.canvasPadding / this.worldTransform.d; - var centerX = (x0 + x1 + x2) / 3; - var centerY = (y0 + y1 + y2) / 3; - - var normX = x0 - centerX; - var normY = y0 - centerY; - - var dist = Math.sqrt(normX * normX + normY * normY); - x0 = centerX + (normX / dist) * (dist + paddingX); - y0 = centerY + (normY / dist) * (dist + paddingY); - - // - - normX = x1 - centerX; - normY = y1 - centerY; - - dist = Math.sqrt(normX * normX + normY * normY); - x1 = centerX + (normX / dist) * (dist + paddingX); - y1 = centerY + (normY / dist) * (dist + paddingY); - - normX = x2 - centerX; - normY = y2 - centerY; - - dist = Math.sqrt(normX * normX + normY * normY); - x2 = centerX + (normX / dist) * (dist + paddingX); - y2 = centerY + (normY / dist) * (dist + paddingY); - } - - context.save(); - context.beginPath(); - - - context.moveTo(x0, y0); - context.lineTo(x1, y1); - context.lineTo(x2, y2); - - context.closePath(); - - context.clip(); - - // Compute matrix transform - var delta = (u0 * v1) + (v0 * u2) + (u1 * v2) - (v1 * u2) - (v0 * u1) - (u0 * v2); - var deltaA = (x0 * v1) + (v0 * x2) + (x1 * v2) - (v1 * x2) - (v0 * x1) - (x0 * v2); - var deltaB = (u0 * x1) + (x0 * u2) + (u1 * x2) - (x1 * u2) - (x0 * u1) - (u0 * x2); - var deltaC = (u0 * v1 * x2) + (v0 * x1 * u2) + (x0 * u1 * v2) - (x0 * v1 * u2) - (v0 * u1 * x2) - (u0 * x1 * v2); - var deltaD = (y0 * v1) + (v0 * y2) + (y1 * v2) - (v1 * y2) - (v0 * y1) - (y0 * v2); - var deltaE = (u0 * y1) + (y0 * u2) + (u1 * y2) - (y1 * u2) - (y0 * u1) - (u0 * y2); - var deltaF = (u0 * v1 * y2) + (v0 * y1 * u2) + (y0 * u1 * v2) - (y0 * v1 * u2) - (v0 * u1 * y2) - (u0 * y1 * v2); - - context.transform(deltaA / delta, deltaD / delta, - deltaB / delta, deltaE / delta, - deltaC / delta, deltaF / delta); - - context.drawImage(textureSource, 0, 0); - context.restore(); -}; - - - -/** - * Renders a flat Mesh - * - * @param Mesh {Mesh} The Mesh to render - * @private - */ -Mesh.prototype.renderMeshFlat = function (Mesh) -{ - var context = this.context; - var vertices = Mesh.vertices; - - var length = vertices.length/2; - // this.count++; - - context.beginPath(); - for (var i=1; i < length-2; i++) - { - // draw some triangles! - var index = i*2; - - var x0 = vertices[index], x1 = vertices[index+2], x2 = vertices[index+4]; - var y0 = vertices[index+1], y1 = vertices[index+3], y2 = vertices[index+5]; - - context.moveTo(x0, y0); - context.lineTo(x1, y1); - context.lineTo(x2, y2); - } - - context.fillStyle = '#FF0000'; - context.fill(); - context.closePath(); -}; - -/* -Mesh.prototype.setTexture = function (texture) -{ - //TODO SET THE TEXTURES - //TODO VISIBILITY - //TODO SETTER - - // stop current texture - this.texture = texture; - this.width = texture.frame.width; - this.height = texture.frame.height; - this.updateFrame = true; -}; - */ - -/** - * When the texture is updated, this event will fire to update the scale and frame - * - * @param event - * @private - */ - -Mesh.prototype.onTextureUpdate = function () -{ - this.updateFrame = true; -}; - -/** - * Returns the bounds of the mesh as a rectangle. The bounds calculation takes the worldTransform into account. - * - * @param matrix {Matrix} the transformation matrix of the sprite - * @return {Rectangle} the framing rectangle - */ -Mesh.prototype.getBounds = function (matrix) -{ - var worldTransform = matrix || this.worldTransform; - - var a = worldTransform.a; - var b = worldTransform.b; - var c = worldTransform.c; - var d = worldTransform.d; - var tx = worldTransform.tx; - var ty = worldTransform.ty; - - var maxX = -Infinity; - var maxY = -Infinity; - - var minX = Infinity; - var minY = Infinity; - - var vertices = this.vertices; - for (var i = 0, n = vertices.length; i < n; i += 2) - { - var rawX = vertices[i], rawY = vertices[i + 1]; - var x = (a * rawX) + (c * rawY) + tx; - var y = (d * rawY) + (b * rawX) + ty; - - minX = x < minX ? x : minX; - minY = y < minY ? y : minY; - - maxX = x > maxX ? x : maxX; - maxY = y > maxY ? y : maxY; - } - - if (minX === -Infinity || maxY === Infinity) - { - return core.math.Rectangle.EMPTY; - } - - var bounds = this._bounds; - - bounds.x = minX; - bounds.width = maxX - minX; - - bounds.y = minY; - bounds.height = maxY - minY; - - // store a reference so that if this function gets called again in the render cycle we do not have to recalculate - this._currentBounds = bounds; - - return bounds; -}; - -/** - * Different drawing buffer modes supported - * - * @static - * @constant - * @property {object} DRAW_MODES - * @property {number} DRAW_MODES.TRIANGLE_MESH - * @property {number} DRAW_MODES.TRIANGLES - */ -Mesh.DRAW_MODES = { - TRIANGLE_MESH: 0, - TRIANGLES: 1 -}; diff --git a/src/extras/mesh/Rope.js b/src/extras/mesh/Rope.js deleted file mode 100644 index 8119995..0000000 --- a/src/extras/mesh/Rope.js +++ /dev/null @@ -1,192 +0,0 @@ -var Mesh = require('./Mesh'); - -/** - * The rope allows you to draw a texture across several points and them manipulate these points - * - *```js - * for (var i = 0; i < 20; i++) { - * points.push(new PIXI.Point(i * 50, 0)); - * }; - * var rope = new PIXI.Rope(PIXI.Texture.fromImage("snake.png"), points); - * ``` - * - * @class - * @extends Mesh - * @memberof PIXI.extras - * @param {Texture} texture - The texture to use on the rope. - * @param {Array} points - An array of {Point} objects to construct this rope. - * - */ -function Rope(texture, points) -{ - Mesh.call(this, texture); - - /* - * @member {Array} An array of points that determine the rope - */ - this.points = points; - - /* - * @member {Float32Array} An array of vertices used to construct this rope. - */ - this.vertices = new Float32Array(points.length * 4); - - /* - * @member {Float32Array} The WebGL Uvs of the rope. - */ - this.uvs = new Float32Array(points.length * 4); - - /* - * @member {Float32Array} An array containing the color components - */ - this.colors = new Float32Array(points.length * 2); - - /* - * @member {Uint16Array} An array containing the indices of the vertices - */ - this.indices = new Uint16Array(points.length * 2); - - this.refresh(); -} - - -// constructor -Rope.prototype = Object.create(Mesh.prototype); -Rope.prototype.constructor = Rope; -module.exports = Rope; - -/** - * Refreshes - * - */ -Rope.prototype.refresh = function () -{ - var points = this.points; - - if (points.length < 1) - { - return; - } - - var uvs = this.uvs; - - var indices = this.indices; - var colors = this.colors; - - // this.count -= 0.2; - - uvs[0] = 0; - uvs[1] = 0; - uvs[2] = 0; - uvs[3] = 1; - - colors[0] = 1; - colors[1] = 1; - - indices[0] = 0; - indices[1] = 1; - - var total = points.length, - point, index, amount; - - for (var i = 1; i < total; i++) - { - point = points[i]; - index = i * 4; - // time to do some smart drawing! - amount = i / (total-1); - - if (i%2) - { - uvs[index] = amount; - uvs[index+1] = 0; - - uvs[index+2] = amount; - uvs[index+3] = 1; - } - else - { - uvs[index] = amount; - uvs[index+1] = 0; - - uvs[index+2] = amount; - uvs[index+3] = 1; - } - - index = i * 2; - colors[index] = 1; - colors[index+1] = 1; - - index = i * 2; - indices[index] = index; - indices[index + 1] = index + 1; - } -}; - -/* - * Updates the object transform for rendering - * - * @private - */ -Rope.prototype.updateTransform = function () -{ - var points = this.points; - - if (points.length < 1) - { - return; - } - - var lastPoint = points[0]; - var nextPoint; - var perpX = 0; - var perpY = 0; - - // this.count -= 0.2; - - var vertices = this.vertices; - var total = points.length, - point, index, ratio, perpLength, num; - - for (var i = 0; i < total; i++) - { - point = points[i]; - index = i * 4; - - if (i < points.length-1) - { - nextPoint = points[i+1]; - } - else - { - nextPoint = point; - } - - perpY = -(nextPoint.x - lastPoint.x); - perpX = nextPoint.y - lastPoint.y; - - ratio = (1 - (i / (total-1))) * 10; - - if (ratio > 1) - { - ratio = 1; - } - - perpLength = Math.sqrt(perpX * perpX + perpY * perpY); - num = this.texture.height / 2; //(20 + Math.abs(Math.sin((i + this.count) * 0.3) * 50) )* ratio; - perpX /= perpLength; - perpY /= perpLength; - - perpX *= num; - perpY *= num; - - vertices[index] = point.x + perpX; - vertices[index+1] = point.y + perpY; - vertices[index+2] = point.x - perpX; - vertices[index+3] = point.y - perpY; - - lastPoint = point; - } - - this.containerUpdateTransform(); -}; diff --git a/src/extras/mesh/index.js b/src/extras/mesh/index.js deleted file mode 100644 index dd37f87..0000000 --- a/src/extras/mesh/index.js +++ /dev/null @@ -1,16 +0,0 @@ -/** - * @file Main export of the PIXI extras library - * @author Mat Groves - * @copyright 2013-2015 GoodBoyDigital - * @license {@link https://github.com/GoodBoyDigital/pixi.js/blob/master/LICENSE|MIT License} - */ - -/** - * @namespace PIXI.extras - */ -module.exports = { - Mesh: require('./Mesh'), - Rope: require('./Rope'), - MeshRenderer: require('./webgl/MeshRenderer'), - MeshShader: require('./webgl/MeshShader') -}; diff --git a/src/extras/mesh/webgl/MeshRenderer.js b/src/extras/mesh/webgl/MeshRenderer.js deleted file mode 100644 index 2dd7678..0000000 --- a/src/extras/mesh/webgl/MeshRenderer.js +++ /dev/null @@ -1,215 +0,0 @@ -var ObjectRenderer = require('../../../core/renderers/webgl/utils/ObjectRenderer'), - WebGLRenderer = require('../../../core/renderers/webgl/WebGLRenderer'); - -/** - * @author Mat Groves - * - * Big thanks to the very clever Matt DesLauriers https://github.com/mattdesl/ - * for creating the original pixi version! - * Also a thanks to https://github.com/bchevalier for tweaking the tint and alpha so that they now share 4 bytes on the vertex buffer - * - * Heavily inspired by LibGDX's MeshRenderer: - * https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/graphics/g2d/MeshRenderer.java - */ - -/** - * - * @class - * @private - * @memberof PIXI - * @extends ObjectRenderer - * @param renderer {WebGLRenderer} The renderer this sprite batch works for. - */ -function MeshRenderer(renderer) -{ - ObjectRenderer.call(this, renderer); - - - /** - * Holds the indices - * - * @member {Uint16Array} - */ - this.indices = new Uint16Array(15000); - - //TODO this could be a single buffer shared amongst all renderers as we reuse this set up in most renderers - for (var i=0, j=0; i < 15000; i += 6, j += 4) - { - this.indices[i + 0] = j + 0; - this.indices[i + 1] = j + 1; - this.indices[i + 2] = j + 2; - this.indices[i + 3] = j + 0; - this.indices[i + 4] = j + 2; - this.indices[i + 5] = j + 3; - } -} - -MeshRenderer.prototype = Object.create(ObjectRenderer.prototype); -MeshRenderer.prototype.constructor = MeshRenderer; -module.exports = MeshRenderer; - -WebGLRenderer.registerPlugin('mesh', MeshRenderer); - -/** - * Sets up the renderer context and necessary buffers. - * - * @private - * @param gl {WebGLRenderingContext} the current WebGL drawing context - */ -MeshRenderer.prototype.onContextChange = function () -{ - -}; - -/** - * Renders the sprite object. - * - * @param mesh {Mesh} the mesh to render - */ -MeshRenderer.prototype.render = function (mesh) -{ -// return; - if(!mesh._vertexBuffer) - { - this._initWebGL(mesh); - } - - var renderer = this.renderer, - gl = renderer.gl, - texture = mesh.texture.baseTexture, - shader = renderer.shaderManager.plugins.meshShader; - -// var drawMode = mesh.drawMode === Strip.DRAW_MODES.TRIANGLE_STRIP ? gl.TRIANGLE_STRIP : gl.TRIANGLES; - var drawMode = gl.TRIANGLE_STRIP; - - renderer.blendModeManager.setBlendMode(mesh.blendMode); - - - // set uniforms - gl.uniformMatrix3fv(shader.uniforms.translationMatrix._location, false, mesh.worldTransform.toArray(true)); - - gl.uniformMatrix3fv(shader.uniforms.projectionMatrix._location, false, renderer.currentRenderTarget.projectionMatrix.toArray(true)); - gl.uniform1f(shader.uniforms.alpha._location, mesh.worldAlpha); - - if (!mesh.dirty) - { - - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._vertexBuffer); - gl.bufferSubData(gl.ARRAY_BUFFER, 0, mesh.vertices); - gl.vertexAttribPointer(shader.attributes.aVertexPosition, 2, gl.FLOAT, false, 0, 0); - - - // update the uvs - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._uvBuffer); - gl.vertexAttribPointer(shader.attributes.aTextureCoord, 2, gl.FLOAT, false, 0, 0); - - - gl.activeTexture(gl.TEXTURE0); - - if (!texture._glTextures[gl.id]) - { - this.renderer.updateTexture(texture); - } - else - { - // bind the current texture - gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]); - } - } - else - { - - mesh.dirty = false; - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER, mesh.vertices, gl.STATIC_DRAW); - gl.vertexAttribPointer(shader.attributes.aVertexPosition, 2, gl.FLOAT, false, 0, 0); - - // update the uvs - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._uvBuffer); - gl.bufferData(gl.ARRAY_BUFFER, mesh.uvs, gl.STATIC_DRAW); - gl.vertexAttribPointer(shader.attributes.aTextureCoord, 2, gl.FLOAT, false, 0, 0); - - gl.activeTexture(gl.TEXTURE0); - - if (!texture._glTextures[gl.id]) - { - this.renderer.updateTexture(texture); - } - else - { - // bind the current texture - gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]); - } - - // dont need to upload! - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, mesh._indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, mesh.indices, gl.STATIC_DRAW); - - } - - gl.drawElements(drawMode, mesh.indices.length, gl.UNSIGNED_SHORT, 0); - -}; - -/** - * Prepares all the buffers to render this mesh - * @param mesh {Mesh} the mesh to render - */ -MeshRenderer.prototype._initWebGL = function (mesh) -{ - // build the strip! - var gl = this.renderer.gl; - - mesh._vertexBuffer = gl.createBuffer(); - mesh._indexBuffer = gl.createBuffer(); - mesh._uvBuffer = gl.createBuffer(); - mesh._colorBuffer = gl.createBuffer(); - - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER, mesh.vertices, gl.DYNAMIC_DRAW); - - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._uvBuffer); - gl.bufferData(gl.ARRAY_BUFFER, mesh.uvs, gl.STATIC_DRAW); - - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._colorBuffer); - gl.bufferData(gl.ARRAY_BUFFER, mesh.colors, gl.STATIC_DRAW); - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, mesh._indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, mesh.indices, gl.STATIC_DRAW); -}; - - -/** - * Empties the current batch. - * - */ -MeshRenderer.prototype.flush = function () -{ - -}; - -/** - * Starts a new mesh renderer. - * - */ -MeshRenderer.prototype.start = function () -{ - var gl = this.renderer.gl, - shader = this.renderer.shaderManager.plugins.meshShader; - - this.renderer.shaderManager.setShader(shader); - - // dont need to upload! - //gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indices); - - - // this.s -}; - -/** - * Destroys the Mesh renderer - * - */ -MeshRenderer.prototype.destroy = function () -{ -}; diff --git a/src/extras/mesh/webgl/MeshShader.js b/src/extras/mesh/webgl/MeshShader.js deleted file mode 100644 index 51c03f5..0000000 --- a/src/extras/mesh/webgl/MeshShader.js +++ /dev/null @@ -1,59 +0,0 @@ -var core = require('../../../core'); - -/** - * @class - * @extends Shader - * @memberof PIXI.extras - * @param shaderManager {ShaderManager} The WebGL shader manager this shader works for. - */ -function StripShader(shaderManager) -{ - core.Shader.call(this, - shaderManager, - // vertex shader - [ - 'precision lowp float;', - 'attribute vec2 aVertexPosition;', - 'attribute vec2 aTextureCoord;', - - 'uniform mat3 translationMatrix;', - 'uniform mat3 projectionMatrix;', - - 'varying vec2 vTextureCoord;', - - 'void main(void){', - ' gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);', - ' vTextureCoord = aTextureCoord;', - '}' - ].join('\n'), - [ - 'precision lowp float;', - - 'varying vec2 vTextureCoord;', - 'uniform float alpha;', - - 'uniform sampler2D uSampler;', - - 'void main(void){', - ' gl_FragColor = texture2D(uSampler, vTextureCoord) * alpha ;', - '}' - ].join('\n'), - // custom uniforms - { - alpha: { type: '1f', value: 0 }, - translationMatrix: { type: 'mat3', value: new Float32Array(9) }, - projectionMatrix: { type: 'mat3', value: new Float32Array(9) } - }, - // custom attributes - { - aVertexPosition:0, - aTextureCoord:0 - } - ); -} - -StripShader.prototype = Object.create(core.Shader.prototype); -StripShader.prototype.constructor = StripShader; -module.exports = StripShader; - -core.ShaderManager.registerPlugin('meshShader', StripShader); diff --git a/src/index.js b/src/index.js index 2c1f999..da8c001 100644 --- a/src/index.js +++ b/src/index.js @@ -1,6 +1,7 @@ var core = require('./core'); extendCore(require('./extras')); +extendCore(require('./mesh')); extendCore(require('./filters')); extendCore(require('./interaction')); extendCore(require('./loaders')); diff --git a/src/mesh/Mesh.js b/src/mesh/Mesh.js new file mode 100644 index 0000000..c006078 --- /dev/null +++ b/src/mesh/Mesh.js @@ -0,0 +1,387 @@ +var core = require('../core'); + +/** + * Base mesh class + * @class + * @extends Container + * @memberof PIXI.extras + * @param texture {Texture} The texture to use + * @param [vertices] {Float32Arrif you want to specify the vertices + * @param [uvs] {Float32Array} if you want to specify the uvs + * @param [indices] {Uint16Array} if you want to specify the indices + * @param [drawMode] {number} the drawMode, can be any of the Mesh.DRAW_MODES consts + */ +function Mesh(texture, vertices, uvs, indices, drawMode) +{ + core.Container.call(this); + + /** + * The texture of the Mesh + * + * @member {Texture} + */ + this.texture = texture; + + /** + * The Uvs of the Mesh + * + * @member {Float32Array} + */ + this.uvs = uvs || new Float32Array([0, 1, + 1, 1, + 1, 0, + 0, 1]); + + /** + * An array of vertices + * + * @member {Float32Array} + */ + this.vertices = vertices || new Float32Array([0, 0, + 100, 0, + 100, 100, + 0, 100]); + + /* + * @member {Uint16Array} An array containing the indices of the vertices + */ + // TODO auto generate this based on draw mode! + this.indices = indices || new Uint16Array([0, 1, 2, 3]); + + /** + * Whether the Mesh is dirty or not + * + * @member {boolean} + */ + this.dirty = true; + + /** + * The blend mode to be applied to the sprite. Set to blendModes.NORMAL to remove any blend mode. + * + * @member {number} + * @default CONST.BLEND_MODES.NORMAL; + */ + this.blendMode = core.CONST.BLEND_MODES.NORMAL; + + /** + * Triangles in canvas mode are automatically antialiased, use this value to force triangles to overlap a bit with each other. + * + * @member {number}= + */ + this.canvasPadding = 0; + + /** + * The way the Mesh should be drawn, can be any of the Mesh.DRAW_MODES consts + * + * @member {number} + */ + this.drawMode = drawMode || Mesh.DRAW_MODES.TRIANGLE_MESH; +} + +// constructor +Mesh.prototype = Object.create(core.Container.prototype); +Mesh.prototype.constructor = Mesh; +module.exports = Mesh; + +/** + * Renders the object using the WebGL renderer + * + * @param renderer {WebGLRenderer} a reference to the WebGL renderer + */ +Mesh.prototype._renderWebGL = function (renderer) +{ + renderer.setObjectRenderer(renderer.plugins.mesh); + renderer.plugins.mesh.render(this); +}; + +/** + * Renders the object using the Canvas renderer + * + * @param renderer {CanvasRenderer} + */ +Mesh.prototype._renderCanvas = function (renderer) +{ + var context = renderer.context; + + var transform = this.worldTransform; + + if (renderer.roundPixels) + { + context.setTransform(transform.a, transform.b, transform.c, transform.d, transform.tx | 0, transform.ty | 0); + } + else + { + context.setTransform(transform.a, transform.b, transform.c, transform.d, transform.tx, transform.ty); + } + + if (this.drawMode === Mesh.DRAW_MODES.TRIANGLE_MESH) + { + this._renderCanvasTriangleMesh(context); + } + else + { + this._renderCanvasTriangles(context); + } +}; + +/** + * Draws the object in Triangle Mesh mode using canvas + * + * @param context {CanvasRenderingContext2D} the current drawing context + * @private + */ +Mesh.prototype._renderCanvasTriangleMesh = function (context) +{ + // draw triangles!! + var vertices = this.vertices; + var uvs = this.uvs; + + var length = vertices.length / 2; + // this.count++; + + for (var i = 0; i < length - 2; i++) + { + // draw some triangles! + var index = i * 2; + this._renderCanvasDrawTriangle(context, vertices, uvs, index, (index + 2), (index + 4)); + } +}; + +/** + * Draws the object in triangle mode using canvas + * + * @param context {CanvasRenderingContext2D} the current drawing context + * @private + */ +Mesh.prototype._renderCanvasTriangles = function (context) +{ + // draw triangles!! + var vertices = this.vertices; + var uvs = this.uvs; + var indices = this.indices; + + var length = indices.length; + // this.count++; + + for (var i = 0; i < length; i += 3) + { + // draw some triangles! + var index0 = indices[i] * 2, index1 = indices[i + 1] * 2, index2 = indices[i + 2] * 2; + this._renderCanvasDrawTriangle(context, vertices, uvs, index0, index1, index2); + } +}; + +/** + * Draws one of the triangles that form this Mesh + * + * @param context {CanvasRenderingContext2D} the current drawing context + * @param vertices {Float32Array} a reference to the vertices of the Mesh + * @param uvs {Float32Array} a reference to the uvs of the Mesh + * @param index0 {number} the index of the first vertex + * @param index1 {number} the index of the second vertex + * @param index2 {number} the index of the third vertex + * @private + */ +Mesh.prototype._renderCanvasDrawTriangle = function (context, vertices, uvs, index0, index1, index2) +{ + var textureSource = this.texture.baseTexture.source; + var textureWidth = this.texture.width; + var textureHeight = this.texture.height; + + var x0 = vertices[index0], x1 = vertices[index1], x2 = vertices[index2]; + var y0 = vertices[index0 + 1], y1 = vertices[index1 + 1], y2 = vertices[index2 + 1]; + + var u0 = uvs[index0] * textureWidth, u1 = uvs[index1] * textureWidth, u2 = uvs[index2] * textureWidth; + var v0 = uvs[index0 + 1] * textureHeight, v1 = uvs[index1 + 1] * textureHeight, v2 = uvs[index2 + 1] * textureHeight; + + if (this.canvasPadding > 0) + { + var paddingX = this.canvasPadding / this.worldTransform.a; + var paddingY = this.canvasPadding / this.worldTransform.d; + var centerX = (x0 + x1 + x2) / 3; + var centerY = (y0 + y1 + y2) / 3; + + var normX = x0 - centerX; + var normY = y0 - centerY; + + var dist = Math.sqrt(normX * normX + normY * normY); + x0 = centerX + (normX / dist) * (dist + paddingX); + y0 = centerY + (normY / dist) * (dist + paddingY); + + // + + normX = x1 - centerX; + normY = y1 - centerY; + + dist = Math.sqrt(normX * normX + normY * normY); + x1 = centerX + (normX / dist) * (dist + paddingX); + y1 = centerY + (normY / dist) * (dist + paddingY); + + normX = x2 - centerX; + normY = y2 - centerY; + + dist = Math.sqrt(normX * normX + normY * normY); + x2 = centerX + (normX / dist) * (dist + paddingX); + y2 = centerY + (normY / dist) * (dist + paddingY); + } + + context.save(); + context.beginPath(); + + + context.moveTo(x0, y0); + context.lineTo(x1, y1); + context.lineTo(x2, y2); + + context.closePath(); + + context.clip(); + + // Compute matrix transform + var delta = (u0 * v1) + (v0 * u2) + (u1 * v2) - (v1 * u2) - (v0 * u1) - (u0 * v2); + var deltaA = (x0 * v1) + (v0 * x2) + (x1 * v2) - (v1 * x2) - (v0 * x1) - (x0 * v2); + var deltaB = (u0 * x1) + (x0 * u2) + (u1 * x2) - (x1 * u2) - (x0 * u1) - (u0 * x2); + var deltaC = (u0 * v1 * x2) + (v0 * x1 * u2) + (x0 * u1 * v2) - (x0 * v1 * u2) - (v0 * u1 * x2) - (u0 * x1 * v2); + var deltaD = (y0 * v1) + (v0 * y2) + (y1 * v2) - (v1 * y2) - (v0 * y1) - (y0 * v2); + var deltaE = (u0 * y1) + (y0 * u2) + (u1 * y2) - (y1 * u2) - (y0 * u1) - (u0 * y2); + var deltaF = (u0 * v1 * y2) + (v0 * y1 * u2) + (y0 * u1 * v2) - (y0 * v1 * u2) - (v0 * u1 * y2) - (u0 * y1 * v2); + + context.transform(deltaA / delta, deltaD / delta, + deltaB / delta, deltaE / delta, + deltaC / delta, deltaF / delta); + + context.drawImage(textureSource, 0, 0); + context.restore(); +}; + + + +/** + * Renders a flat Mesh + * + * @param Mesh {Mesh} The Mesh to render + * @private + */ +Mesh.prototype.renderMeshFlat = function (Mesh) +{ + var context = this.context; + var vertices = Mesh.vertices; + + var length = vertices.length/2; + // this.count++; + + context.beginPath(); + for (var i=1; i < length-2; i++) + { + // draw some triangles! + var index = i*2; + + var x0 = vertices[index], x1 = vertices[index+2], x2 = vertices[index+4]; + var y0 = vertices[index+1], y1 = vertices[index+3], y2 = vertices[index+5]; + + context.moveTo(x0, y0); + context.lineTo(x1, y1); + context.lineTo(x2, y2); + } + + context.fillStyle = '#FF0000'; + context.fill(); + context.closePath(); +}; + +/* +Mesh.prototype.setTexture = function (texture) +{ + //TODO SET THE TEXTURES + //TODO VISIBILITY + //TODO SETTER + + // stop current texture + this.texture = texture; + this.width = texture.frame.width; + this.height = texture.frame.height; + this.updateFrame = true; +}; + */ + +/** + * When the texture is updated, this event will fire to update the scale and frame + * + * @param event + * @private + */ + +Mesh.prototype.onTextureUpdate = function () +{ + this.updateFrame = true; +}; + +/** + * Returns the bounds of the mesh as a rectangle. The bounds calculation takes the worldTransform into account. + * + * @param matrix {Matrix} the transformation matrix of the sprite + * @return {Rectangle} the framing rectangle + */ +Mesh.prototype.getBounds = function (matrix) +{ + var worldTransform = matrix || this.worldTransform; + + var a = worldTransform.a; + var b = worldTransform.b; + var c = worldTransform.c; + var d = worldTransform.d; + var tx = worldTransform.tx; + var ty = worldTransform.ty; + + var maxX = -Infinity; + var maxY = -Infinity; + + var minX = Infinity; + var minY = Infinity; + + var vertices = this.vertices; + for (var i = 0, n = vertices.length; i < n; i += 2) + { + var rawX = vertices[i], rawY = vertices[i + 1]; + var x = (a * rawX) + (c * rawY) + tx; + var y = (d * rawY) + (b * rawX) + ty; + + minX = x < minX ? x : minX; + minY = y < minY ? y : minY; + + maxX = x > maxX ? x : maxX; + maxY = y > maxY ? y : maxY; + } + + if (minX === -Infinity || maxY === Infinity) + { + return core.math.Rectangle.EMPTY; + } + + var bounds = this._bounds; + + bounds.x = minX; + bounds.width = maxX - minX; + + bounds.y = minY; + bounds.height = maxY - minY; + + // store a reference so that if this function gets called again in the render cycle we do not have to recalculate + this._currentBounds = bounds; + + return bounds; +}; + +/** + * Different drawing buffer modes supported + * + * @static + * @constant + * @property {object} DRAW_MODES + * @property {number} DRAW_MODES.TRIANGLE_MESH + * @property {number} DRAW_MODES.TRIANGLES + */ +Mesh.DRAW_MODES = { + TRIANGLE_MESH: 0, + TRIANGLES: 1 +}; diff --git a/src/mesh/Rope.js b/src/mesh/Rope.js new file mode 100644 index 0000000..8119995 --- /dev/null +++ b/src/mesh/Rope.js @@ -0,0 +1,192 @@ +var Mesh = require('./Mesh'); + +/** + * The rope allows you to draw a texture across several points and them manipulate these points + * + *```js + * for (var i = 0; i < 20; i++) { + * points.push(new PIXI.Point(i * 50, 0)); + * }; + * var rope = new PIXI.Rope(PIXI.Texture.fromImage("snake.png"), points); + * ``` + * + * @class + * @extends Mesh + * @memberof PIXI.extras + * @param {Texture} texture - The texture to use on the rope. + * @param {Array} points - An array of {Point} objects to construct this rope. + * + */ +function Rope(texture, points) +{ + Mesh.call(this, texture); + + /* + * @member {Array} An array of points that determine the rope + */ + this.points = points; + + /* + * @member {Float32Array} An array of vertices used to construct this rope. + */ + this.vertices = new Float32Array(points.length * 4); + + /* + * @member {Float32Array} The WebGL Uvs of the rope. + */ + this.uvs = new Float32Array(points.length * 4); + + /* + * @member {Float32Array} An array containing the color components + */ + this.colors = new Float32Array(points.length * 2); + + /* + * @member {Uint16Array} An array containing the indices of the vertices + */ + this.indices = new Uint16Array(points.length * 2); + + this.refresh(); +} + + +// constructor +Rope.prototype = Object.create(Mesh.prototype); +Rope.prototype.constructor = Rope; +module.exports = Rope; + +/** + * Refreshes + * + */ +Rope.prototype.refresh = function () +{ + var points = this.points; + + if (points.length < 1) + { + return; + } + + var uvs = this.uvs; + + var indices = this.indices; + var colors = this.colors; + + // this.count -= 0.2; + + uvs[0] = 0; + uvs[1] = 0; + uvs[2] = 0; + uvs[3] = 1; + + colors[0] = 1; + colors[1] = 1; + + indices[0] = 0; + indices[1] = 1; + + var total = points.length, + point, index, amount; + + for (var i = 1; i < total; i++) + { + point = points[i]; + index = i * 4; + // time to do some smart drawing! + amount = i / (total-1); + + if (i%2) + { + uvs[index] = amount; + uvs[index+1] = 0; + + uvs[index+2] = amount; + uvs[index+3] = 1; + } + else + { + uvs[index] = amount; + uvs[index+1] = 0; + + uvs[index+2] = amount; + uvs[index+3] = 1; + } + + index = i * 2; + colors[index] = 1; + colors[index+1] = 1; + + index = i * 2; + indices[index] = index; + indices[index + 1] = index + 1; + } +}; + +/* + * Updates the object transform for rendering + * + * @private + */ +Rope.prototype.updateTransform = function () +{ + var points = this.points; + + if (points.length < 1) + { + return; + } + + var lastPoint = points[0]; + var nextPoint; + var perpX = 0; + var perpY = 0; + + // this.count -= 0.2; + + var vertices = this.vertices; + var total = points.length, + point, index, ratio, perpLength, num; + + for (var i = 0; i < total; i++) + { + point = points[i]; + index = i * 4; + + if (i < points.length-1) + { + nextPoint = points[i+1]; + } + else + { + nextPoint = point; + } + + perpY = -(nextPoint.x - lastPoint.x); + perpX = nextPoint.y - lastPoint.y; + + ratio = (1 - (i / (total-1))) * 10; + + if (ratio > 1) + { + ratio = 1; + } + + perpLength = Math.sqrt(perpX * perpX + perpY * perpY); + num = this.texture.height / 2; //(20 + Math.abs(Math.sin((i + this.count) * 0.3) * 50) )* ratio; + perpX /= perpLength; + perpY /= perpLength; + + perpX *= num; + perpY *= num; + + vertices[index] = point.x + perpX; + vertices[index+1] = point.y + perpY; + vertices[index+2] = point.x - perpX; + vertices[index+3] = point.y - perpY; + + lastPoint = point; + } + + this.containerUpdateTransform(); +}; diff --git a/src/mesh/index.js b/src/mesh/index.js new file mode 100644 index 0000000..dd37f87 --- /dev/null +++ b/src/mesh/index.js @@ -0,0 +1,16 @@ +/** + * @file Main export of the PIXI extras library + * @author Mat Groves + * @copyright 2013-2015 GoodBoyDigital + * @license {@link https://github.com/GoodBoyDigital/pixi.js/blob/master/LICENSE|MIT License} + */ + +/** + * @namespace PIXI.extras + */ +module.exports = { + Mesh: require('./Mesh'), + Rope: require('./Rope'), + MeshRenderer: require('./webgl/MeshRenderer'), + MeshShader: require('./webgl/MeshShader') +}; diff --git a/src/mesh/webgl/MeshRenderer.js b/src/mesh/webgl/MeshRenderer.js new file mode 100644 index 0000000..a1e1ebc --- /dev/null +++ b/src/mesh/webgl/MeshRenderer.js @@ -0,0 +1,215 @@ +var ObjectRenderer = require('../../core/renderers/webgl/utils/ObjectRenderer'), + WebGLRenderer = require('../../core/renderers/webgl/WebGLRenderer'); + +/** + * @author Mat Groves + * + * Big thanks to the very clever Matt DesLauriers https://github.com/mattdesl/ + * for creating the original pixi version! + * Also a thanks to https://github.com/bchevalier for tweaking the tint and alpha so that they now share 4 bytes on the vertex buffer + * + * Heavily inspired by LibGDX's MeshRenderer: + * https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/graphics/g2d/MeshRenderer.java + */ + +/** + * + * @class + * @private + * @memberof PIXI + * @extends ObjectRenderer + * @param renderer {WebGLRenderer} The renderer this sprite batch works for. + */ +function MeshRenderer(renderer) +{ + ObjectRenderer.call(this, renderer); + + + /** + * Holds the indices + * + * @member {Uint16Array} + */ + this.indices = new Uint16Array(15000); + + //TODO this could be a single buffer shared amongst all renderers as we reuse this set up in most renderers + for (var i=0, j=0; i < 15000; i += 6, j += 4) + { + this.indices[i + 0] = j + 0; + this.indices[i + 1] = j + 1; + this.indices[i + 2] = j + 2; + this.indices[i + 3] = j + 0; + this.indices[i + 4] = j + 2; + this.indices[i + 5] = j + 3; + } +} + +MeshRenderer.prototype = Object.create(ObjectRenderer.prototype); +MeshRenderer.prototype.constructor = MeshRenderer; +module.exports = MeshRenderer; + +WebGLRenderer.registerPlugin('mesh', MeshRenderer); + +/** + * Sets up the renderer context and necessary buffers. + * + * @private + * @param gl {WebGLRenderingContext} the current WebGL drawing context + */ +MeshRenderer.prototype.onContextChange = function () +{ + +}; + +/** + * Renders the sprite object. + * + * @param mesh {Mesh} the mesh to render + */ +MeshRenderer.prototype.render = function (mesh) +{ +// return; + if(!mesh._vertexBuffer) + { + this._initWebGL(mesh); + } + + var renderer = this.renderer, + gl = renderer.gl, + texture = mesh.texture.baseTexture, + shader = renderer.shaderManager.plugins.meshShader; + +// var drawMode = mesh.drawMode === Strip.DRAW_MODES.TRIANGLE_STRIP ? gl.TRIANGLE_STRIP : gl.TRIANGLES; + var drawMode = gl.TRIANGLE_STRIP; + + renderer.blendModeManager.setBlendMode(mesh.blendMode); + + + // set uniforms + gl.uniformMatrix3fv(shader.uniforms.translationMatrix._location, false, mesh.worldTransform.toArray(true)); + + gl.uniformMatrix3fv(shader.uniforms.projectionMatrix._location, false, renderer.currentRenderTarget.projectionMatrix.toArray(true)); + gl.uniform1f(shader.uniforms.alpha._location, mesh.worldAlpha); + + if (!mesh.dirty) + { + + gl.bindBuffer(gl.ARRAY_BUFFER, mesh._vertexBuffer); + gl.bufferSubData(gl.ARRAY_BUFFER, 0, mesh.vertices); + gl.vertexAttribPointer(shader.attributes.aVertexPosition, 2, gl.FLOAT, false, 0, 0); + + + // update the uvs + gl.bindBuffer(gl.ARRAY_BUFFER, mesh._uvBuffer); + gl.vertexAttribPointer(shader.attributes.aTextureCoord, 2, gl.FLOAT, false, 0, 0); + + + gl.activeTexture(gl.TEXTURE0); + + if (!texture._glTextures[gl.id]) + { + this.renderer.updateTexture(texture); + } + else + { + // bind the current texture + gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]); + } + } + else + { + + mesh.dirty = false; + gl.bindBuffer(gl.ARRAY_BUFFER, mesh._vertexBuffer); + gl.bufferData(gl.ARRAY_BUFFER, mesh.vertices, gl.STATIC_DRAW); + gl.vertexAttribPointer(shader.attributes.aVertexPosition, 2, gl.FLOAT, false, 0, 0); + + // update the uvs + gl.bindBuffer(gl.ARRAY_BUFFER, mesh._uvBuffer); + gl.bufferData(gl.ARRAY_BUFFER, mesh.uvs, gl.STATIC_DRAW); + gl.vertexAttribPointer(shader.attributes.aTextureCoord, 2, gl.FLOAT, false, 0, 0); + + gl.activeTexture(gl.TEXTURE0); + + if (!texture._glTextures[gl.id]) + { + this.renderer.updateTexture(texture); + } + else + { + // bind the current texture + gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]); + } + + // dont need to upload! + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, mesh._indexBuffer); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, mesh.indices, gl.STATIC_DRAW); + + } + + gl.drawElements(drawMode, mesh.indices.length, gl.UNSIGNED_SHORT, 0); + +}; + +/** + * Prepares all the buffers to render this mesh + * @param mesh {Mesh} the mesh to render + */ +MeshRenderer.prototype._initWebGL = function (mesh) +{ + // build the strip! + var gl = this.renderer.gl; + + mesh._vertexBuffer = gl.createBuffer(); + mesh._indexBuffer = gl.createBuffer(); + mesh._uvBuffer = gl.createBuffer(); + mesh._colorBuffer = gl.createBuffer(); + + gl.bindBuffer(gl.ARRAY_BUFFER, mesh._vertexBuffer); + gl.bufferData(gl.ARRAY_BUFFER, mesh.vertices, gl.DYNAMIC_DRAW); + + gl.bindBuffer(gl.ARRAY_BUFFER, mesh._uvBuffer); + gl.bufferData(gl.ARRAY_BUFFER, mesh.uvs, gl.STATIC_DRAW); + + gl.bindBuffer(gl.ARRAY_BUFFER, mesh._colorBuffer); + gl.bufferData(gl.ARRAY_BUFFER, mesh.colors, gl.STATIC_DRAW); + + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, mesh._indexBuffer); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, mesh.indices, gl.STATIC_DRAW); +}; + + +/** + * Empties the current batch. + * + */ +MeshRenderer.prototype.flush = function () +{ + +}; + +/** + * Starts a new mesh renderer. + * + */ +MeshRenderer.prototype.start = function () +{ + var gl = this.renderer.gl, + shader = this.renderer.shaderManager.plugins.meshShader; + + this.renderer.shaderManager.setShader(shader); + + // dont need to upload! + //gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indices); + + + // this.s +}; + +/** + * Destroys the Mesh renderer + * + */ +MeshRenderer.prototype.destroy = function () +{ +}; diff --git a/src/extras/index.js b/src/extras/index.js index 267e97c..6f14e0d 100644 --- a/src/extras/index.js +++ b/src/extras/index.js @@ -11,7 +11,6 @@ module.exports = { MovieClip: require('./MovieClip'), TilingSprite: require('./TilingSprite'), - mesh: require('./mesh/index'), cacheAsBitmap: require('./cacheAsBitmap'), getChildByName: require('./getChildByName') }; diff --git a/src/extras/mesh/Mesh.js b/src/extras/mesh/Mesh.js deleted file mode 100644 index 30431ae..0000000 --- a/src/extras/mesh/Mesh.js +++ /dev/null @@ -1,387 +0,0 @@ -var core = require('../../core'); - -/** - * Base mesh class - * @class - * @extends Container - * @memberof PIXI.extras - * @param texture {Texture} The texture to use - * @param [vertices] {Float32Arrif you want to specify the vertices - * @param [uvs] {Float32Array} if you want to specify the uvs - * @param [indices] {Uint16Array} if you want to specify the indices - * @param [drawMode] {number} the drawMode, can be any of the Mesh.DRAW_MODES consts - */ -function Mesh(texture, vertices, uvs, indices, drawMode) -{ - core.Container.call(this); - - /** - * The texture of the Mesh - * - * @member {Texture} - */ - this.texture = texture; - - /** - * The Uvs of the Mesh - * - * @member {Float32Array} - */ - this.uvs = uvs || new Float32Array([0, 1, - 1, 1, - 1, 0, - 0, 1]); - - /** - * An array of vertices - * - * @member {Float32Array} - */ - this.vertices = vertices || new Float32Array([0, 0, - 100, 0, - 100, 100, - 0, 100]); - - /* - * @member {Uint16Array} An array containing the indices of the vertices - */ - // TODO auto generate this based on draw mode! - this.indices = indices || new Uint16Array([0, 1, 2, 3]); - - /** - * Whether the Mesh is dirty or not - * - * @member {boolean} - */ - this.dirty = true; - - /** - * The blend mode to be applied to the sprite. Set to blendModes.NORMAL to remove any blend mode. - * - * @member {number} - * @default CONST.BLEND_MODES.NORMAL; - */ - this.blendMode = core.CONST.BLEND_MODES.NORMAL; - - /** - * Triangles in canvas mode are automatically antialiased, use this value to force triangles to overlap a bit with each other. - * - * @member {number}= - */ - this.canvasPadding = 0; - - /** - * The way the Mesh should be drawn, can be any of the Mesh.DRAW_MODES consts - * - * @member {number} - */ - this.drawMode = drawMode || Mesh.DRAW_MODES.TRIANGLE_MESH; -} - -// constructor -Mesh.prototype = Object.create(core.Container.prototype); -Mesh.prototype.constructor = Mesh; -module.exports = Mesh; - -/** - * Renders the object using the WebGL renderer - * - * @param renderer {WebGLRenderer} a reference to the WebGL renderer - */ -Mesh.prototype._renderWebGL = function (renderer) -{ - renderer.setObjectRenderer(renderer.plugins.mesh); - renderer.plugins.mesh.render(this); -}; - -/** - * Renders the object using the Canvas renderer - * - * @param renderer {CanvasRenderer} - */ -Mesh.prototype._renderCanvas = function (renderer) -{ - var context = renderer.context; - - var transform = this.worldTransform; - - if (renderer.roundPixels) - { - context.setTransform(transform.a, transform.b, transform.c, transform.d, transform.tx | 0, transform.ty | 0); - } - else - { - context.setTransform(transform.a, transform.b, transform.c, transform.d, transform.tx, transform.ty); - } - - if (this.drawMode === Mesh.DRAW_MODES.TRIANGLE_MESH) - { - this._renderCanvasTriangleMesh(context); - } - else - { - this._renderCanvasTriangles(context); - } -}; - -/** - * Draws the object in Triangle Mesh mode using canvas - * - * @param context {CanvasRenderingContext2D} the current drawing context - * @private - */ -Mesh.prototype._renderCanvasTriangleMesh = function (context) -{ - // draw triangles!! - var vertices = this.vertices; - var uvs = this.uvs; - - var length = vertices.length / 2; - // this.count++; - - for (var i = 0; i < length - 2; i++) - { - // draw some triangles! - var index = i * 2; - this._renderCanvasDrawTriangle(context, vertices, uvs, index, (index + 2), (index + 4)); - } -}; - -/** - * Draws the object in triangle mode using canvas - * - * @param context {CanvasRenderingContext2D} the current drawing context - * @private - */ -Mesh.prototype._renderCanvasTriangles = function (context) -{ - // draw triangles!! - var vertices = this.vertices; - var uvs = this.uvs; - var indices = this.indices; - - var length = indices.length; - // this.count++; - - for (var i = 0; i < length; i += 3) - { - // draw some triangles! - var index0 = indices[i] * 2, index1 = indices[i + 1] * 2, index2 = indices[i + 2] * 2; - this._renderCanvasDrawTriangle(context, vertices, uvs, index0, index1, index2); - } -}; - -/** - * Draws one of the triangles that form this Mesh - * - * @param context {CanvasRenderingContext2D} the current drawing context - * @param vertices {Float32Array} a reference to the vertices of the Mesh - * @param uvs {Float32Array} a reference to the uvs of the Mesh - * @param index0 {number} the index of the first vertex - * @param index1 {number} the index of the second vertex - * @param index2 {number} the index of the third vertex - * @private - */ -Mesh.prototype._renderCanvasDrawTriangle = function (context, vertices, uvs, index0, index1, index2) -{ - var textureSource = this.texture.baseTexture.source; - var textureWidth = this.texture.width; - var textureHeight = this.texture.height; - - var x0 = vertices[index0], x1 = vertices[index1], x2 = vertices[index2]; - var y0 = vertices[index0 + 1], y1 = vertices[index1 + 1], y2 = vertices[index2 + 1]; - - var u0 = uvs[index0] * textureWidth, u1 = uvs[index1] * textureWidth, u2 = uvs[index2] * textureWidth; - var v0 = uvs[index0 + 1] * textureHeight, v1 = uvs[index1 + 1] * textureHeight, v2 = uvs[index2 + 1] * textureHeight; - - if (this.canvasPadding > 0) - { - var paddingX = this.canvasPadding / this.worldTransform.a; - var paddingY = this.canvasPadding / this.worldTransform.d; - var centerX = (x0 + x1 + x2) / 3; - var centerY = (y0 + y1 + y2) / 3; - - var normX = x0 - centerX; - var normY = y0 - centerY; - - var dist = Math.sqrt(normX * normX + normY * normY); - x0 = centerX + (normX / dist) * (dist + paddingX); - y0 = centerY + (normY / dist) * (dist + paddingY); - - // - - normX = x1 - centerX; - normY = y1 - centerY; - - dist = Math.sqrt(normX * normX + normY * normY); - x1 = centerX + (normX / dist) * (dist + paddingX); - y1 = centerY + (normY / dist) * (dist + paddingY); - - normX = x2 - centerX; - normY = y2 - centerY; - - dist = Math.sqrt(normX * normX + normY * normY); - x2 = centerX + (normX / dist) * (dist + paddingX); - y2 = centerY + (normY / dist) * (dist + paddingY); - } - - context.save(); - context.beginPath(); - - - context.moveTo(x0, y0); - context.lineTo(x1, y1); - context.lineTo(x2, y2); - - context.closePath(); - - context.clip(); - - // Compute matrix transform - var delta = (u0 * v1) + (v0 * u2) + (u1 * v2) - (v1 * u2) - (v0 * u1) - (u0 * v2); - var deltaA = (x0 * v1) + (v0 * x2) + (x1 * v2) - (v1 * x2) - (v0 * x1) - (x0 * v2); - var deltaB = (u0 * x1) + (x0 * u2) + (u1 * x2) - (x1 * u2) - (x0 * u1) - (u0 * x2); - var deltaC = (u0 * v1 * x2) + (v0 * x1 * u2) + (x0 * u1 * v2) - (x0 * v1 * u2) - (v0 * u1 * x2) - (u0 * x1 * v2); - var deltaD = (y0 * v1) + (v0 * y2) + (y1 * v2) - (v1 * y2) - (v0 * y1) - (y0 * v2); - var deltaE = (u0 * y1) + (y0 * u2) + (u1 * y2) - (y1 * u2) - (y0 * u1) - (u0 * y2); - var deltaF = (u0 * v1 * y2) + (v0 * y1 * u2) + (y0 * u1 * v2) - (y0 * v1 * u2) - (v0 * u1 * y2) - (u0 * y1 * v2); - - context.transform(deltaA / delta, deltaD / delta, - deltaB / delta, deltaE / delta, - deltaC / delta, deltaF / delta); - - context.drawImage(textureSource, 0, 0); - context.restore(); -}; - - - -/** - * Renders a flat Mesh - * - * @param Mesh {Mesh} The Mesh to render - * @private - */ -Mesh.prototype.renderMeshFlat = function (Mesh) -{ - var context = this.context; - var vertices = Mesh.vertices; - - var length = vertices.length/2; - // this.count++; - - context.beginPath(); - for (var i=1; i < length-2; i++) - { - // draw some triangles! - var index = i*2; - - var x0 = vertices[index], x1 = vertices[index+2], x2 = vertices[index+4]; - var y0 = vertices[index+1], y1 = vertices[index+3], y2 = vertices[index+5]; - - context.moveTo(x0, y0); - context.lineTo(x1, y1); - context.lineTo(x2, y2); - } - - context.fillStyle = '#FF0000'; - context.fill(); - context.closePath(); -}; - -/* -Mesh.prototype.setTexture = function (texture) -{ - //TODO SET THE TEXTURES - //TODO VISIBILITY - //TODO SETTER - - // stop current texture - this.texture = texture; - this.width = texture.frame.width; - this.height = texture.frame.height; - this.updateFrame = true; -}; - */ - -/** - * When the texture is updated, this event will fire to update the scale and frame - * - * @param event - * @private - */ - -Mesh.prototype.onTextureUpdate = function () -{ - this.updateFrame = true; -}; - -/** - * Returns the bounds of the mesh as a rectangle. The bounds calculation takes the worldTransform into account. - * - * @param matrix {Matrix} the transformation matrix of the sprite - * @return {Rectangle} the framing rectangle - */ -Mesh.prototype.getBounds = function (matrix) -{ - var worldTransform = matrix || this.worldTransform; - - var a = worldTransform.a; - var b = worldTransform.b; - var c = worldTransform.c; - var d = worldTransform.d; - var tx = worldTransform.tx; - var ty = worldTransform.ty; - - var maxX = -Infinity; - var maxY = -Infinity; - - var minX = Infinity; - var minY = Infinity; - - var vertices = this.vertices; - for (var i = 0, n = vertices.length; i < n; i += 2) - { - var rawX = vertices[i], rawY = vertices[i + 1]; - var x = (a * rawX) + (c * rawY) + tx; - var y = (d * rawY) + (b * rawX) + ty; - - minX = x < minX ? x : minX; - minY = y < minY ? y : minY; - - maxX = x > maxX ? x : maxX; - maxY = y > maxY ? y : maxY; - } - - if (minX === -Infinity || maxY === Infinity) - { - return core.math.Rectangle.EMPTY; - } - - var bounds = this._bounds; - - bounds.x = minX; - bounds.width = maxX - minX; - - bounds.y = minY; - bounds.height = maxY - minY; - - // store a reference so that if this function gets called again in the render cycle we do not have to recalculate - this._currentBounds = bounds; - - return bounds; -}; - -/** - * Different drawing buffer modes supported - * - * @static - * @constant - * @property {object} DRAW_MODES - * @property {number} DRAW_MODES.TRIANGLE_MESH - * @property {number} DRAW_MODES.TRIANGLES - */ -Mesh.DRAW_MODES = { - TRIANGLE_MESH: 0, - TRIANGLES: 1 -}; diff --git a/src/extras/mesh/Rope.js b/src/extras/mesh/Rope.js deleted file mode 100644 index 8119995..0000000 --- a/src/extras/mesh/Rope.js +++ /dev/null @@ -1,192 +0,0 @@ -var Mesh = require('./Mesh'); - -/** - * The rope allows you to draw a texture across several points and them manipulate these points - * - *```js - * for (var i = 0; i < 20; i++) { - * points.push(new PIXI.Point(i * 50, 0)); - * }; - * var rope = new PIXI.Rope(PIXI.Texture.fromImage("snake.png"), points); - * ``` - * - * @class - * @extends Mesh - * @memberof PIXI.extras - * @param {Texture} texture - The texture to use on the rope. - * @param {Array} points - An array of {Point} objects to construct this rope. - * - */ -function Rope(texture, points) -{ - Mesh.call(this, texture); - - /* - * @member {Array} An array of points that determine the rope - */ - this.points = points; - - /* - * @member {Float32Array} An array of vertices used to construct this rope. - */ - this.vertices = new Float32Array(points.length * 4); - - /* - * @member {Float32Array} The WebGL Uvs of the rope. - */ - this.uvs = new Float32Array(points.length * 4); - - /* - * @member {Float32Array} An array containing the color components - */ - this.colors = new Float32Array(points.length * 2); - - /* - * @member {Uint16Array} An array containing the indices of the vertices - */ - this.indices = new Uint16Array(points.length * 2); - - this.refresh(); -} - - -// constructor -Rope.prototype = Object.create(Mesh.prototype); -Rope.prototype.constructor = Rope; -module.exports = Rope; - -/** - * Refreshes - * - */ -Rope.prototype.refresh = function () -{ - var points = this.points; - - if (points.length < 1) - { - return; - } - - var uvs = this.uvs; - - var indices = this.indices; - var colors = this.colors; - - // this.count -= 0.2; - - uvs[0] = 0; - uvs[1] = 0; - uvs[2] = 0; - uvs[3] = 1; - - colors[0] = 1; - colors[1] = 1; - - indices[0] = 0; - indices[1] = 1; - - var total = points.length, - point, index, amount; - - for (var i = 1; i < total; i++) - { - point = points[i]; - index = i * 4; - // time to do some smart drawing! - amount = i / (total-1); - - if (i%2) - { - uvs[index] = amount; - uvs[index+1] = 0; - - uvs[index+2] = amount; - uvs[index+3] = 1; - } - else - { - uvs[index] = amount; - uvs[index+1] = 0; - - uvs[index+2] = amount; - uvs[index+3] = 1; - } - - index = i * 2; - colors[index] = 1; - colors[index+1] = 1; - - index = i * 2; - indices[index] = index; - indices[index + 1] = index + 1; - } -}; - -/* - * Updates the object transform for rendering - * - * @private - */ -Rope.prototype.updateTransform = function () -{ - var points = this.points; - - if (points.length < 1) - { - return; - } - - var lastPoint = points[0]; - var nextPoint; - var perpX = 0; - var perpY = 0; - - // this.count -= 0.2; - - var vertices = this.vertices; - var total = points.length, - point, index, ratio, perpLength, num; - - for (var i = 0; i < total; i++) - { - point = points[i]; - index = i * 4; - - if (i < points.length-1) - { - nextPoint = points[i+1]; - } - else - { - nextPoint = point; - } - - perpY = -(nextPoint.x - lastPoint.x); - perpX = nextPoint.y - lastPoint.y; - - ratio = (1 - (i / (total-1))) * 10; - - if (ratio > 1) - { - ratio = 1; - } - - perpLength = Math.sqrt(perpX * perpX + perpY * perpY); - num = this.texture.height / 2; //(20 + Math.abs(Math.sin((i + this.count) * 0.3) * 50) )* ratio; - perpX /= perpLength; - perpY /= perpLength; - - perpX *= num; - perpY *= num; - - vertices[index] = point.x + perpX; - vertices[index+1] = point.y + perpY; - vertices[index+2] = point.x - perpX; - vertices[index+3] = point.y - perpY; - - lastPoint = point; - } - - this.containerUpdateTransform(); -}; diff --git a/src/extras/mesh/index.js b/src/extras/mesh/index.js deleted file mode 100644 index dd37f87..0000000 --- a/src/extras/mesh/index.js +++ /dev/null @@ -1,16 +0,0 @@ -/** - * @file Main export of the PIXI extras library - * @author Mat Groves - * @copyright 2013-2015 GoodBoyDigital - * @license {@link https://github.com/GoodBoyDigital/pixi.js/blob/master/LICENSE|MIT License} - */ - -/** - * @namespace PIXI.extras - */ -module.exports = { - Mesh: require('./Mesh'), - Rope: require('./Rope'), - MeshRenderer: require('./webgl/MeshRenderer'), - MeshShader: require('./webgl/MeshShader') -}; diff --git a/src/extras/mesh/webgl/MeshRenderer.js b/src/extras/mesh/webgl/MeshRenderer.js deleted file mode 100644 index 2dd7678..0000000 --- a/src/extras/mesh/webgl/MeshRenderer.js +++ /dev/null @@ -1,215 +0,0 @@ -var ObjectRenderer = require('../../../core/renderers/webgl/utils/ObjectRenderer'), - WebGLRenderer = require('../../../core/renderers/webgl/WebGLRenderer'); - -/** - * @author Mat Groves - * - * Big thanks to the very clever Matt DesLauriers https://github.com/mattdesl/ - * for creating the original pixi version! - * Also a thanks to https://github.com/bchevalier for tweaking the tint and alpha so that they now share 4 bytes on the vertex buffer - * - * Heavily inspired by LibGDX's MeshRenderer: - * https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/graphics/g2d/MeshRenderer.java - */ - -/** - * - * @class - * @private - * @memberof PIXI - * @extends ObjectRenderer - * @param renderer {WebGLRenderer} The renderer this sprite batch works for. - */ -function MeshRenderer(renderer) -{ - ObjectRenderer.call(this, renderer); - - - /** - * Holds the indices - * - * @member {Uint16Array} - */ - this.indices = new Uint16Array(15000); - - //TODO this could be a single buffer shared amongst all renderers as we reuse this set up in most renderers - for (var i=0, j=0; i < 15000; i += 6, j += 4) - { - this.indices[i + 0] = j + 0; - this.indices[i + 1] = j + 1; - this.indices[i + 2] = j + 2; - this.indices[i + 3] = j + 0; - this.indices[i + 4] = j + 2; - this.indices[i + 5] = j + 3; - } -} - -MeshRenderer.prototype = Object.create(ObjectRenderer.prototype); -MeshRenderer.prototype.constructor = MeshRenderer; -module.exports = MeshRenderer; - -WebGLRenderer.registerPlugin('mesh', MeshRenderer); - -/** - * Sets up the renderer context and necessary buffers. - * - * @private - * @param gl {WebGLRenderingContext} the current WebGL drawing context - */ -MeshRenderer.prototype.onContextChange = function () -{ - -}; - -/** - * Renders the sprite object. - * - * @param mesh {Mesh} the mesh to render - */ -MeshRenderer.prototype.render = function (mesh) -{ -// return; - if(!mesh._vertexBuffer) - { - this._initWebGL(mesh); - } - - var renderer = this.renderer, - gl = renderer.gl, - texture = mesh.texture.baseTexture, - shader = renderer.shaderManager.plugins.meshShader; - -// var drawMode = mesh.drawMode === Strip.DRAW_MODES.TRIANGLE_STRIP ? gl.TRIANGLE_STRIP : gl.TRIANGLES; - var drawMode = gl.TRIANGLE_STRIP; - - renderer.blendModeManager.setBlendMode(mesh.blendMode); - - - // set uniforms - gl.uniformMatrix3fv(shader.uniforms.translationMatrix._location, false, mesh.worldTransform.toArray(true)); - - gl.uniformMatrix3fv(shader.uniforms.projectionMatrix._location, false, renderer.currentRenderTarget.projectionMatrix.toArray(true)); - gl.uniform1f(shader.uniforms.alpha._location, mesh.worldAlpha); - - if (!mesh.dirty) - { - - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._vertexBuffer); - gl.bufferSubData(gl.ARRAY_BUFFER, 0, mesh.vertices); - gl.vertexAttribPointer(shader.attributes.aVertexPosition, 2, gl.FLOAT, false, 0, 0); - - - // update the uvs - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._uvBuffer); - gl.vertexAttribPointer(shader.attributes.aTextureCoord, 2, gl.FLOAT, false, 0, 0); - - - gl.activeTexture(gl.TEXTURE0); - - if (!texture._glTextures[gl.id]) - { - this.renderer.updateTexture(texture); - } - else - { - // bind the current texture - gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]); - } - } - else - { - - mesh.dirty = false; - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER, mesh.vertices, gl.STATIC_DRAW); - gl.vertexAttribPointer(shader.attributes.aVertexPosition, 2, gl.FLOAT, false, 0, 0); - - // update the uvs - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._uvBuffer); - gl.bufferData(gl.ARRAY_BUFFER, mesh.uvs, gl.STATIC_DRAW); - gl.vertexAttribPointer(shader.attributes.aTextureCoord, 2, gl.FLOAT, false, 0, 0); - - gl.activeTexture(gl.TEXTURE0); - - if (!texture._glTextures[gl.id]) - { - this.renderer.updateTexture(texture); - } - else - { - // bind the current texture - gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]); - } - - // dont need to upload! - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, mesh._indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, mesh.indices, gl.STATIC_DRAW); - - } - - gl.drawElements(drawMode, mesh.indices.length, gl.UNSIGNED_SHORT, 0); - -}; - -/** - * Prepares all the buffers to render this mesh - * @param mesh {Mesh} the mesh to render - */ -MeshRenderer.prototype._initWebGL = function (mesh) -{ - // build the strip! - var gl = this.renderer.gl; - - mesh._vertexBuffer = gl.createBuffer(); - mesh._indexBuffer = gl.createBuffer(); - mesh._uvBuffer = gl.createBuffer(); - mesh._colorBuffer = gl.createBuffer(); - - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER, mesh.vertices, gl.DYNAMIC_DRAW); - - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._uvBuffer); - gl.bufferData(gl.ARRAY_BUFFER, mesh.uvs, gl.STATIC_DRAW); - - gl.bindBuffer(gl.ARRAY_BUFFER, mesh._colorBuffer); - gl.bufferData(gl.ARRAY_BUFFER, mesh.colors, gl.STATIC_DRAW); - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, mesh._indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, mesh.indices, gl.STATIC_DRAW); -}; - - -/** - * Empties the current batch. - * - */ -MeshRenderer.prototype.flush = function () -{ - -}; - -/** - * Starts a new mesh renderer. - * - */ -MeshRenderer.prototype.start = function () -{ - var gl = this.renderer.gl, - shader = this.renderer.shaderManager.plugins.meshShader; - - this.renderer.shaderManager.setShader(shader); - - // dont need to upload! - //gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indices); - - - // this.s -}; - -/** - * Destroys the Mesh renderer - * - */ -MeshRenderer.prototype.destroy = function () -{ -}; diff --git a/src/extras/mesh/webgl/MeshShader.js b/src/extras/mesh/webgl/MeshShader.js deleted file mode 100644 index 51c03f5..0000000 --- a/src/extras/mesh/webgl/MeshShader.js +++ /dev/null @@ -1,59 +0,0 @@ -var core = require('../../../core'); - -/** - * @class - * @extends Shader - * @memberof PIXI.extras - * @param shaderManager {ShaderManager} The WebGL shader manager this shader works for. - */ -function StripShader(shaderManager) -{ - core.Shader.call(this, - shaderManager, - // vertex shader - [ - 'precision lowp float;', - 'attribute vec2 aVertexPosition;', - 'attribute vec2 aTextureCoord;', - - 'uniform mat3 translationMatrix;', - 'uniform mat3 projectionMatrix;', - - 'varying vec2 vTextureCoord;', - - 'void main(void){', - ' gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);', - ' vTextureCoord = aTextureCoord;', - '}' - ].join('\n'), - [ - 'precision lowp float;', - - 'varying vec2 vTextureCoord;', - 'uniform float alpha;', - - 'uniform sampler2D uSampler;', - - 'void main(void){', - ' gl_FragColor = texture2D(uSampler, vTextureCoord) * alpha ;', - '}' - ].join('\n'), - // custom uniforms - { - alpha: { type: '1f', value: 0 }, - translationMatrix: { type: 'mat3', value: new Float32Array(9) }, - projectionMatrix: { type: 'mat3', value: new Float32Array(9) } - }, - // custom attributes - { - aVertexPosition:0, - aTextureCoord:0 - } - ); -} - -StripShader.prototype = Object.create(core.Shader.prototype); -StripShader.prototype.constructor = StripShader; -module.exports = StripShader; - -core.ShaderManager.registerPlugin('meshShader', StripShader); diff --git a/src/index.js b/src/index.js index 2c1f999..da8c001 100644 --- a/src/index.js +++ b/src/index.js @@ -1,6 +1,7 @@ var core = require('./core'); extendCore(require('./extras')); +extendCore(require('./mesh')); extendCore(require('./filters')); extendCore(require('./interaction')); extendCore(require('./loaders')); diff --git a/src/mesh/Mesh.js b/src/mesh/Mesh.js new file mode 100644 index 0000000..c006078 --- /dev/null +++ b/src/mesh/Mesh.js @@ -0,0 +1,387 @@ +var core = require('../core'); + +/** + * Base mesh class + * @class + * @extends Container + * @memberof PIXI.extras + * @param texture {Texture} The texture to use + * @param [vertices] {Float32Arrif you want to specify the vertices + * @param [uvs] {Float32Array} if you want to specify the uvs + * @param [indices] {Uint16Array} if you want to specify the indices + * @param [drawMode] {number} the drawMode, can be any of the Mesh.DRAW_MODES consts + */ +function Mesh(texture, vertices, uvs, indices, drawMode) +{ + core.Container.call(this); + + /** + * The texture of the Mesh + * + * @member {Texture} + */ + this.texture = texture; + + /** + * The Uvs of the Mesh + * + * @member {Float32Array} + */ + this.uvs = uvs || new Float32Array([0, 1, + 1, 1, + 1, 0, + 0, 1]); + + /** + * An array of vertices + * + * @member {Float32Array} + */ + this.vertices = vertices || new Float32Array([0, 0, + 100, 0, + 100, 100, + 0, 100]); + + /* + * @member {Uint16Array} An array containing the indices of the vertices + */ + // TODO auto generate this based on draw mode! + this.indices = indices || new Uint16Array([0, 1, 2, 3]); + + /** + * Whether the Mesh is dirty or not + * + * @member {boolean} + */ + this.dirty = true; + + /** + * The blend mode to be applied to the sprite. Set to blendModes.NORMAL to remove any blend mode. + * + * @member {number} + * @default CONST.BLEND_MODES.NORMAL; + */ + this.blendMode = core.CONST.BLEND_MODES.NORMAL; + + /** + * Triangles in canvas mode are automatically antialiased, use this value to force triangles to overlap a bit with each other. + * + * @member {number}= + */ + this.canvasPadding = 0; + + /** + * The way the Mesh should be drawn, can be any of the Mesh.DRAW_MODES consts + * + * @member {number} + */ + this.drawMode = drawMode || Mesh.DRAW_MODES.TRIANGLE_MESH; +} + +// constructor +Mesh.prototype = Object.create(core.Container.prototype); +Mesh.prototype.constructor = Mesh; +module.exports = Mesh; + +/** + * Renders the object using the WebGL renderer + * + * @param renderer {WebGLRenderer} a reference to the WebGL renderer + */ +Mesh.prototype._renderWebGL = function (renderer) +{ + renderer.setObjectRenderer(renderer.plugins.mesh); + renderer.plugins.mesh.render(this); +}; + +/** + * Renders the object using the Canvas renderer + * + * @param renderer {CanvasRenderer} + */ +Mesh.prototype._renderCanvas = function (renderer) +{ + var context = renderer.context; + + var transform = this.worldTransform; + + if (renderer.roundPixels) + { + context.setTransform(transform.a, transform.b, transform.c, transform.d, transform.tx | 0, transform.ty | 0); + } + else + { + context.setTransform(transform.a, transform.b, transform.c, transform.d, transform.tx, transform.ty); + } + + if (this.drawMode === Mesh.DRAW_MODES.TRIANGLE_MESH) + { + this._renderCanvasTriangleMesh(context); + } + else + { + this._renderCanvasTriangles(context); + } +}; + +/** + * Draws the object in Triangle Mesh mode using canvas + * + * @param context {CanvasRenderingContext2D} the current drawing context + * @private + */ +Mesh.prototype._renderCanvasTriangleMesh = function (context) +{ + // draw triangles!! + var vertices = this.vertices; + var uvs = this.uvs; + + var length = vertices.length / 2; + // this.count++; + + for (var i = 0; i < length - 2; i++) + { + // draw some triangles! + var index = i * 2; + this._renderCanvasDrawTriangle(context, vertices, uvs, index, (index + 2), (index + 4)); + } +}; + +/** + * Draws the object in triangle mode using canvas + * + * @param context {CanvasRenderingContext2D} the current drawing context + * @private + */ +Mesh.prototype._renderCanvasTriangles = function (context) +{ + // draw triangles!! + var vertices = this.vertices; + var uvs = this.uvs; + var indices = this.indices; + + var length = indices.length; + // this.count++; + + for (var i = 0; i < length; i += 3) + { + // draw some triangles! + var index0 = indices[i] * 2, index1 = indices[i + 1] * 2, index2 = indices[i + 2] * 2; + this._renderCanvasDrawTriangle(context, vertices, uvs, index0, index1, index2); + } +}; + +/** + * Draws one of the triangles that form this Mesh + * + * @param context {CanvasRenderingContext2D} the current drawing context + * @param vertices {Float32Array} a reference to the vertices of the Mesh + * @param uvs {Float32Array} a reference to the uvs of the Mesh + * @param index0 {number} the index of the first vertex + * @param index1 {number} the index of the second vertex + * @param index2 {number} the index of the third vertex + * @private + */ +Mesh.prototype._renderCanvasDrawTriangle = function (context, vertices, uvs, index0, index1, index2) +{ + var textureSource = this.texture.baseTexture.source; + var textureWidth = this.texture.width; + var textureHeight = this.texture.height; + + var x0 = vertices[index0], x1 = vertices[index1], x2 = vertices[index2]; + var y0 = vertices[index0 + 1], y1 = vertices[index1 + 1], y2 = vertices[index2 + 1]; + + var u0 = uvs[index0] * textureWidth, u1 = uvs[index1] * textureWidth, u2 = uvs[index2] * textureWidth; + var v0 = uvs[index0 + 1] * textureHeight, v1 = uvs[index1 + 1] * textureHeight, v2 = uvs[index2 + 1] * textureHeight; + + if (this.canvasPadding > 0) + { + var paddingX = this.canvasPadding / this.worldTransform.a; + var paddingY = this.canvasPadding / this.worldTransform.d; + var centerX = (x0 + x1 + x2) / 3; + var centerY = (y0 + y1 + y2) / 3; + + var normX = x0 - centerX; + var normY = y0 - centerY; + + var dist = Math.sqrt(normX * normX + normY * normY); + x0 = centerX + (normX / dist) * (dist + paddingX); + y0 = centerY + (normY / dist) * (dist + paddingY); + + // + + normX = x1 - centerX; + normY = y1 - centerY; + + dist = Math.sqrt(normX * normX + normY * normY); + x1 = centerX + (normX / dist) * (dist + paddingX); + y1 = centerY + (normY / dist) * (dist + paddingY); + + normX = x2 - centerX; + normY = y2 - centerY; + + dist = Math.sqrt(normX * normX + normY * normY); + x2 = centerX + (normX / dist) * (dist + paddingX); + y2 = centerY + (normY / dist) * (dist + paddingY); + } + + context.save(); + context.beginPath(); + + + context.moveTo(x0, y0); + context.lineTo(x1, y1); + context.lineTo(x2, y2); + + context.closePath(); + + context.clip(); + + // Compute matrix transform + var delta = (u0 * v1) + (v0 * u2) + (u1 * v2) - (v1 * u2) - (v0 * u1) - (u0 * v2); + var deltaA = (x0 * v1) + (v0 * x2) + (x1 * v2) - (v1 * x2) - (v0 * x1) - (x0 * v2); + var deltaB = (u0 * x1) + (x0 * u2) + (u1 * x2) - (x1 * u2) - (x0 * u1) - (u0 * x2); + var deltaC = (u0 * v1 * x2) + (v0 * x1 * u2) + (x0 * u1 * v2) - (x0 * v1 * u2) - (v0 * u1 * x2) - (u0 * x1 * v2); + var deltaD = (y0 * v1) + (v0 * y2) + (y1 * v2) - (v1 * y2) - (v0 * y1) - (y0 * v2); + var deltaE = (u0 * y1) + (y0 * u2) + (u1 * y2) - (y1 * u2) - (y0 * u1) - (u0 * y2); + var deltaF = (u0 * v1 * y2) + (v0 * y1 * u2) + (y0 * u1 * v2) - (y0 * v1 * u2) - (v0 * u1 * y2) - (u0 * y1 * v2); + + context.transform(deltaA / delta, deltaD / delta, + deltaB / delta, deltaE / delta, + deltaC / delta, deltaF / delta); + + context.drawImage(textureSource, 0, 0); + context.restore(); +}; + + + +/** + * Renders a flat Mesh + * + * @param Mesh {Mesh} The Mesh to render + * @private + */ +Mesh.prototype.renderMeshFlat = function (Mesh) +{ + var context = this.context; + var vertices = Mesh.vertices; + + var length = vertices.length/2; + // this.count++; + + context.beginPath(); + for (var i=1; i < length-2; i++) + { + // draw some triangles! + var index = i*2; + + var x0 = vertices[index], x1 = vertices[index+2], x2 = vertices[index+4]; + var y0 = vertices[index+1], y1 = vertices[index+3], y2 = vertices[index+5]; + + context.moveTo(x0, y0); + context.lineTo(x1, y1); + context.lineTo(x2, y2); + } + + context.fillStyle = '#FF0000'; + context.fill(); + context.closePath(); +}; + +/* +Mesh.prototype.setTexture = function (texture) +{ + //TODO SET THE TEXTURES + //TODO VISIBILITY + //TODO SETTER + + // stop current texture + this.texture = texture; + this.width = texture.frame.width; + this.height = texture.frame.height; + this.updateFrame = true; +}; + */ + +/** + * When the texture is updated, this event will fire to update the scale and frame + * + * @param event + * @private + */ + +Mesh.prototype.onTextureUpdate = function () +{ + this.updateFrame = true; +}; + +/** + * Returns the bounds of the mesh as a rectangle. The bounds calculation takes the worldTransform into account. + * + * @param matrix {Matrix} the transformation matrix of the sprite + * @return {Rectangle} the framing rectangle + */ +Mesh.prototype.getBounds = function (matrix) +{ + var worldTransform = matrix || this.worldTransform; + + var a = worldTransform.a; + var b = worldTransform.b; + var c = worldTransform.c; + var d = worldTransform.d; + var tx = worldTransform.tx; + var ty = worldTransform.ty; + + var maxX = -Infinity; + var maxY = -Infinity; + + var minX = Infinity; + var minY = Infinity; + + var vertices = this.vertices; + for (var i = 0, n = vertices.length; i < n; i += 2) + { + var rawX = vertices[i], rawY = vertices[i + 1]; + var x = (a * rawX) + (c * rawY) + tx; + var y = (d * rawY) + (b * rawX) + ty; + + minX = x < minX ? x : minX; + minY = y < minY ? y : minY; + + maxX = x > maxX ? x : maxX; + maxY = y > maxY ? y : maxY; + } + + if (minX === -Infinity || maxY === Infinity) + { + return core.math.Rectangle.EMPTY; + } + + var bounds = this._bounds; + + bounds.x = minX; + bounds.width = maxX - minX; + + bounds.y = minY; + bounds.height = maxY - minY; + + // store a reference so that if this function gets called again in the render cycle we do not have to recalculate + this._currentBounds = bounds; + + return bounds; +}; + +/** + * Different drawing buffer modes supported + * + * @static + * @constant + * @property {object} DRAW_MODES + * @property {number} DRAW_MODES.TRIANGLE_MESH + * @property {number} DRAW_MODES.TRIANGLES + */ +Mesh.DRAW_MODES = { + TRIANGLE_MESH: 0, + TRIANGLES: 1 +}; diff --git a/src/mesh/Rope.js b/src/mesh/Rope.js new file mode 100644 index 0000000..8119995 --- /dev/null +++ b/src/mesh/Rope.js @@ -0,0 +1,192 @@ +var Mesh = require('./Mesh'); + +/** + * The rope allows you to draw a texture across several points and them manipulate these points + * + *```js + * for (var i = 0; i < 20; i++) { + * points.push(new PIXI.Point(i * 50, 0)); + * }; + * var rope = new PIXI.Rope(PIXI.Texture.fromImage("snake.png"), points); + * ``` + * + * @class + * @extends Mesh + * @memberof PIXI.extras + * @param {Texture} texture - The texture to use on the rope. + * @param {Array} points - An array of {Point} objects to construct this rope. + * + */ +function Rope(texture, points) +{ + Mesh.call(this, texture); + + /* + * @member {Array} An array of points that determine the rope + */ + this.points = points; + + /* + * @member {Float32Array} An array of vertices used to construct this rope. + */ + this.vertices = new Float32Array(points.length * 4); + + /* + * @member {Float32Array} The WebGL Uvs of the rope. + */ + this.uvs = new Float32Array(points.length * 4); + + /* + * @member {Float32Array} An array containing the color components + */ + this.colors = new Float32Array(points.length * 2); + + /* + * @member {Uint16Array} An array containing the indices of the vertices + */ + this.indices = new Uint16Array(points.length * 2); + + this.refresh(); +} + + +// constructor +Rope.prototype = Object.create(Mesh.prototype); +Rope.prototype.constructor = Rope; +module.exports = Rope; + +/** + * Refreshes + * + */ +Rope.prototype.refresh = function () +{ + var points = this.points; + + if (points.length < 1) + { + return; + } + + var uvs = this.uvs; + + var indices = this.indices; + var colors = this.colors; + + // this.count -= 0.2; + + uvs[0] = 0; + uvs[1] = 0; + uvs[2] = 0; + uvs[3] = 1; + + colors[0] = 1; + colors[1] = 1; + + indices[0] = 0; + indices[1] = 1; + + var total = points.length, + point, index, amount; + + for (var i = 1; i < total; i++) + { + point = points[i]; + index = i * 4; + // time to do some smart drawing! + amount = i / (total-1); + + if (i%2) + { + uvs[index] = amount; + uvs[index+1] = 0; + + uvs[index+2] = amount; + uvs[index+3] = 1; + } + else + { + uvs[index] = amount; + uvs[index+1] = 0; + + uvs[index+2] = amount; + uvs[index+3] = 1; + } + + index = i * 2; + colors[index] = 1; + colors[index+1] = 1; + + index = i * 2; + indices[index] = index; + indices[index + 1] = index + 1; + } +}; + +/* + * Updates the object transform for rendering + * + * @private + */ +Rope.prototype.updateTransform = function () +{ + var points = this.points; + + if (points.length < 1) + { + return; + } + + var lastPoint = points[0]; + var nextPoint; + var perpX = 0; + var perpY = 0; + + // this.count -= 0.2; + + var vertices = this.vertices; + var total = points.length, + point, index, ratio, perpLength, num; + + for (var i = 0; i < total; i++) + { + point = points[i]; + index = i * 4; + + if (i < points.length-1) + { + nextPoint = points[i+1]; + } + else + { + nextPoint = point; + } + + perpY = -(nextPoint.x - lastPoint.x); + perpX = nextPoint.y - lastPoint.y; + + ratio = (1 - (i / (total-1))) * 10; + + if (ratio > 1) + { + ratio = 1; + } + + perpLength = Math.sqrt(perpX * perpX + perpY * perpY); + num = this.texture.height / 2; //(20 + Math.abs(Math.sin((i + this.count) * 0.3) * 50) )* ratio; + perpX /= perpLength; + perpY /= perpLength; + + perpX *= num; + perpY *= num; + + vertices[index] = point.x + perpX; + vertices[index+1] = point.y + perpY; + vertices[index+2] = point.x - perpX; + vertices[index+3] = point.y - perpY; + + lastPoint = point; + } + + this.containerUpdateTransform(); +}; diff --git a/src/mesh/index.js b/src/mesh/index.js new file mode 100644 index 0000000..dd37f87 --- /dev/null +++ b/src/mesh/index.js @@ -0,0 +1,16 @@ +/** + * @file Main export of the PIXI extras library + * @author Mat Groves + * @copyright 2013-2015 GoodBoyDigital + * @license {@link https://github.com/GoodBoyDigital/pixi.js/blob/master/LICENSE|MIT License} + */ + +/** + * @namespace PIXI.extras + */ +module.exports = { + Mesh: require('./Mesh'), + Rope: require('./Rope'), + MeshRenderer: require('./webgl/MeshRenderer'), + MeshShader: require('./webgl/MeshShader') +}; diff --git a/src/mesh/webgl/MeshRenderer.js b/src/mesh/webgl/MeshRenderer.js new file mode 100644 index 0000000..a1e1ebc --- /dev/null +++ b/src/mesh/webgl/MeshRenderer.js @@ -0,0 +1,215 @@ +var ObjectRenderer = require('../../core/renderers/webgl/utils/ObjectRenderer'), + WebGLRenderer = require('../../core/renderers/webgl/WebGLRenderer'); + +/** + * @author Mat Groves + * + * Big thanks to the very clever Matt DesLauriers https://github.com/mattdesl/ + * for creating the original pixi version! + * Also a thanks to https://github.com/bchevalier for tweaking the tint and alpha so that they now share 4 bytes on the vertex buffer + * + * Heavily inspired by LibGDX's MeshRenderer: + * https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/graphics/g2d/MeshRenderer.java + */ + +/** + * + * @class + * @private + * @memberof PIXI + * @extends ObjectRenderer + * @param renderer {WebGLRenderer} The renderer this sprite batch works for. + */ +function MeshRenderer(renderer) +{ + ObjectRenderer.call(this, renderer); + + + /** + * Holds the indices + * + * @member {Uint16Array} + */ + this.indices = new Uint16Array(15000); + + //TODO this could be a single buffer shared amongst all renderers as we reuse this set up in most renderers + for (var i=0, j=0; i < 15000; i += 6, j += 4) + { + this.indices[i + 0] = j + 0; + this.indices[i + 1] = j + 1; + this.indices[i + 2] = j + 2; + this.indices[i + 3] = j + 0; + this.indices[i + 4] = j + 2; + this.indices[i + 5] = j + 3; + } +} + +MeshRenderer.prototype = Object.create(ObjectRenderer.prototype); +MeshRenderer.prototype.constructor = MeshRenderer; +module.exports = MeshRenderer; + +WebGLRenderer.registerPlugin('mesh', MeshRenderer); + +/** + * Sets up the renderer context and necessary buffers. + * + * @private + * @param gl {WebGLRenderingContext} the current WebGL drawing context + */ +MeshRenderer.prototype.onContextChange = function () +{ + +}; + +/** + * Renders the sprite object. + * + * @param mesh {Mesh} the mesh to render + */ +MeshRenderer.prototype.render = function (mesh) +{ +// return; + if(!mesh._vertexBuffer) + { + this._initWebGL(mesh); + } + + var renderer = this.renderer, + gl = renderer.gl, + texture = mesh.texture.baseTexture, + shader = renderer.shaderManager.plugins.meshShader; + +// var drawMode = mesh.drawMode === Strip.DRAW_MODES.TRIANGLE_STRIP ? gl.TRIANGLE_STRIP : gl.TRIANGLES; + var drawMode = gl.TRIANGLE_STRIP; + + renderer.blendModeManager.setBlendMode(mesh.blendMode); + + + // set uniforms + gl.uniformMatrix3fv(shader.uniforms.translationMatrix._location, false, mesh.worldTransform.toArray(true)); + + gl.uniformMatrix3fv(shader.uniforms.projectionMatrix._location, false, renderer.currentRenderTarget.projectionMatrix.toArray(true)); + gl.uniform1f(shader.uniforms.alpha._location, mesh.worldAlpha); + + if (!mesh.dirty) + { + + gl.bindBuffer(gl.ARRAY_BUFFER, mesh._vertexBuffer); + gl.bufferSubData(gl.ARRAY_BUFFER, 0, mesh.vertices); + gl.vertexAttribPointer(shader.attributes.aVertexPosition, 2, gl.FLOAT, false, 0, 0); + + + // update the uvs + gl.bindBuffer(gl.ARRAY_BUFFER, mesh._uvBuffer); + gl.vertexAttribPointer(shader.attributes.aTextureCoord, 2, gl.FLOAT, false, 0, 0); + + + gl.activeTexture(gl.TEXTURE0); + + if (!texture._glTextures[gl.id]) + { + this.renderer.updateTexture(texture); + } + else + { + // bind the current texture + gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]); + } + } + else + { + + mesh.dirty = false; + gl.bindBuffer(gl.ARRAY_BUFFER, mesh._vertexBuffer); + gl.bufferData(gl.ARRAY_BUFFER, mesh.vertices, gl.STATIC_DRAW); + gl.vertexAttribPointer(shader.attributes.aVertexPosition, 2, gl.FLOAT, false, 0, 0); + + // update the uvs + gl.bindBuffer(gl.ARRAY_BUFFER, mesh._uvBuffer); + gl.bufferData(gl.ARRAY_BUFFER, mesh.uvs, gl.STATIC_DRAW); + gl.vertexAttribPointer(shader.attributes.aTextureCoord, 2, gl.FLOAT, false, 0, 0); + + gl.activeTexture(gl.TEXTURE0); + + if (!texture._glTextures[gl.id]) + { + this.renderer.updateTexture(texture); + } + else + { + // bind the current texture + gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]); + } + + // dont need to upload! + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, mesh._indexBuffer); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, mesh.indices, gl.STATIC_DRAW); + + } + + gl.drawElements(drawMode, mesh.indices.length, gl.UNSIGNED_SHORT, 0); + +}; + +/** + * Prepares all the buffers to render this mesh + * @param mesh {Mesh} the mesh to render + */ +MeshRenderer.prototype._initWebGL = function (mesh) +{ + // build the strip! + var gl = this.renderer.gl; + + mesh._vertexBuffer = gl.createBuffer(); + mesh._indexBuffer = gl.createBuffer(); + mesh._uvBuffer = gl.createBuffer(); + mesh._colorBuffer = gl.createBuffer(); + + gl.bindBuffer(gl.ARRAY_BUFFER, mesh._vertexBuffer); + gl.bufferData(gl.ARRAY_BUFFER, mesh.vertices, gl.DYNAMIC_DRAW); + + gl.bindBuffer(gl.ARRAY_BUFFER, mesh._uvBuffer); + gl.bufferData(gl.ARRAY_BUFFER, mesh.uvs, gl.STATIC_DRAW); + + gl.bindBuffer(gl.ARRAY_BUFFER, mesh._colorBuffer); + gl.bufferData(gl.ARRAY_BUFFER, mesh.colors, gl.STATIC_DRAW); + + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, mesh._indexBuffer); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, mesh.indices, gl.STATIC_DRAW); +}; + + +/** + * Empties the current batch. + * + */ +MeshRenderer.prototype.flush = function () +{ + +}; + +/** + * Starts a new mesh renderer. + * + */ +MeshRenderer.prototype.start = function () +{ + var gl = this.renderer.gl, + shader = this.renderer.shaderManager.plugins.meshShader; + + this.renderer.shaderManager.setShader(shader); + + // dont need to upload! + //gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indices); + + + // this.s +}; + +/** + * Destroys the Mesh renderer + * + */ +MeshRenderer.prototype.destroy = function () +{ +}; diff --git a/src/mesh/webgl/MeshShader.js b/src/mesh/webgl/MeshShader.js new file mode 100644 index 0000000..af2f4d7 --- /dev/null +++ b/src/mesh/webgl/MeshShader.js @@ -0,0 +1,59 @@ +var core = require('../../core'); + +/** + * @class + * @extends Shader + * @memberof PIXI.extras + * @param shaderManager {ShaderManager} The WebGL shader manager this shader works for. + */ +function StripShader(shaderManager) +{ + core.Shader.call(this, + shaderManager, + // vertex shader + [ + 'precision lowp float;', + 'attribute vec2 aVertexPosition;', + 'attribute vec2 aTextureCoord;', + + 'uniform mat3 translationMatrix;', + 'uniform mat3 projectionMatrix;', + + 'varying vec2 vTextureCoord;', + + 'void main(void){', + ' gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);', + ' vTextureCoord = aTextureCoord;', + '}' + ].join('\n'), + [ + 'precision lowp float;', + + 'varying vec2 vTextureCoord;', + 'uniform float alpha;', + + 'uniform sampler2D uSampler;', + + 'void main(void){', + ' gl_FragColor = texture2D(uSampler, vTextureCoord) * alpha ;', + '}' + ].join('\n'), + // custom uniforms + { + alpha: { type: '1f', value: 0 }, + translationMatrix: { type: 'mat3', value: new Float32Array(9) }, + projectionMatrix: { type: 'mat3', value: new Float32Array(9) } + }, + // custom attributes + { + aVertexPosition:0, + aTextureCoord:0 + } + ); +} + +StripShader.prototype = Object.create(core.Shader.prototype); +StripShader.prototype.constructor = StripShader; +module.exports = StripShader; + +core.ShaderManager.registerPlugin('meshShader', StripShader);