diff --git a/package-lock.json b/package-lock.json index 41c96ea8f6..916363530b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "p5", - "version": "2.0.0-beta.7", + "version": "2.0.0-beta.8", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "p5", - "version": "2.0.0-beta.7", + "version": "2.0.0-beta.8", "license": "LGPL-2.1", "dependencies": { "@davepagurek/bezier-path": "^0.0.2", diff --git a/src/core/p5.Graphics.js b/src/core/p5.Graphics.js index 751ec51fde..7ee9d9306d 100644 --- a/src/core/p5.Graphics.js +++ b/src/core/p5.Graphics.js @@ -9,7 +9,7 @@ import { RGB, HSB, HSL } from '../color/creating_reading'; import primitives2D from '../shape/2d_primitives'; import attributes from '../shape/attributes'; import curves from '../shape/curves'; -import vertex from '../shape/vertex'; +import customShapes from '../shape/custom_shapes'; import setting from '../color/setting'; import image from '../image/image'; import loadingDisplaying from '../image/loading_displaying'; @@ -676,7 +676,7 @@ function graphics(p5, fn){ primitives2D(p5, p5.Graphics.prototype); attributes(p5, p5.Graphics.prototype); curves(p5, p5.Graphics.prototype); - vertex(p5, p5.Graphics.prototype); + customShapes(p5, p5.Graphics.prototype); setting(p5, p5.Graphics.prototype); loadingDisplaying(p5, p5.Graphics.prototype); diff --git a/src/core/package.json b/src/core/package.json new file mode 100644 index 0000000000..96ae6e57eb --- /dev/null +++ b/src/core/package.json @@ -0,0 +1,3 @@ +{ + "type": "module" +} \ No newline at end of file diff --git a/src/shape/custom_shapes.js b/src/shape/custom_shapes.js index 9eea6efb68..6db68fcc94 100644 --- a/src/shape/custom_shapes.js +++ b/src/shape/custom_shapes.js @@ -6,7 +6,6 @@ * @requires constants */ -// REMINDER: remove .js extension (currently using it to run file locally) import { Color } from '../color/p5.Color'; import { Vector } from '../math/p5.Vector'; import * as constants from '../core/constants'; @@ -1583,25 +1582,1594 @@ function customShapes(p5, fn) { // ---- FUNCTIONS ---- + /** + * Begins creating a hole within a flat shape. + * + * The `beginContour()` and endContour() + * functions allow for creating negative space within custom shapes that are + * flat. `beginContour()` begins adding vertices to a negative space and + * endContour() stops adding them. + * `beginContour()` and endContour() must be + * called between beginShape() and + * endShape(). + * + * Transformations such as translate(), + * rotate(), and scale() + * don't work between `beginContour()` and + * endContour(). It's also not possible to use + * other shapes, such as ellipse() or + * rect(), between `beginContour()` and + * endContour(). + * + * Note: The vertices that define a negative space must "wind" in the opposite + * direction from the outer shape. First, draw vertices for the outer shape + * clockwise order. Then, draw vertices for the negative space in + * counter-clockwise order. + * + * @method beginContour + * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Start drawing the shape. + * beginShape(); + * + * // Exterior vertices, clockwise winding. + * vertex(10, 10); + * vertex(90, 10); + * vertex(90, 90); + * vertex(10, 90); + * + * // Interior vertices, counter-clockwise winding. + * beginContour(); + * vertex(30, 30); + * vertex(30, 70); + * vertex(70, 70); + * vertex(70, 30); + * endContour(); + * + * // Stop drawing the shape. + * endShape(CLOSE); + * + * describe('A white square with a square hole in its center drawn on a gray background.'); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white square with a square hole in its center drawn on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Start drawing the shape. + * beginShape(); + * + * // Exterior vertices, clockwise winding. + * vertex(-40, -40); + * vertex(40, -40); + * vertex(40, 40); + * vertex(-40, 40); + * + * // Interior vertices, counter-clockwise winding. + * beginContour(); + * vertex(-20, -20); + * vertex(-20, 20); + * vertex(20, 20); + * vertex(20, -20); + * endContour(); + * + * // Stop drawing the shape. + * endShape(CLOSE); + * } + * + *
+ */ + fn.beginContour = function(kind) { + this._renderer.beginContour(kind); + }; + + /** + * Begins adding vertices to a custom shape. + * + * The `beginShape()` and endShape() functions + * allow for creating custom shapes in 2D or 3D. `beginShape()` begins adding + * vertices to a custom shape and endShape() stops + * adding them. + * + * The parameter, `kind`, sets the kind of shape to make. The available kinds are: + * + * - `PATH` (the default) to draw shapes by tracing out the path along their edges. + * - `POINTS` to draw a series of points. + * - `LINES` to draw a series of unconnected line segments. + * - `TRIANGLES` to draw a series of separate triangles. + * - `TRIANGLE_FAN` to draw a series of connected triangles sharing the first vertex in a fan-like fashion. + * - `TRIANGLE_STRIP` to draw a series of connected triangles in strip fashion. + * - `QUADS` to draw a series of separate quadrilaterals (quads). + * - `QUAD_STRIP` to draw quad strip using adjacent edges to form the next quad. + * + * After calling `beginShape()`, shapes can be built by calling + * vertex(), + * bezierVertex(), + * bezierVertex(), and/or + * splineVertex(). Calling + * endShape() will stop adding vertices to the + * shape. Each shape will be outlined with the current stroke color and filled + * with the current fill color. + * + * Transformations such as translate(), + * rotate(), and + * scale() don't work between `beginShape()` and + * endShape(). It's also not possible to use + * other shapes, such as ellipse() or + * rect(), between `beginShape()` and + * endShape(). + * + * @method beginShape + * @param {(POINTS|LINES|TRIANGLES|TRIANGLE_FAN|TRIANGLE_STRIP|QUADS|QUAD_STRIP|PATH)} [kind=PATH] either POINTS, LINES, TRIANGLES, TRIANGLE_FAN + * TRIANGLE_STRIP, QUADS, QUAD_STRIP or PATH. Defaults to PATH. + * @chainable + * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Start drawing the shape. + * beginShape(); + * + * // Add vertices. + * vertex(30, 20); + * vertex(85, 20); + * vertex(85, 75); + * vertex(30, 75); + * + * // Stop drawing the shape. + * endShape(CLOSE); + * + * describe('A white square on a gray background.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Start drawing the shape. + * // Only draw the vertices (points). + * beginShape(POINTS); + * + * // Add vertices. + * vertex(30, 20); + * vertex(85, 20); + * vertex(85, 75); + * vertex(30, 75); + * + * // Stop drawing the shape. + * endShape(); + * + * describe('Four black dots that form a square are drawn on a gray background.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Start drawing the shape. + * // Only draw lines between alternating pairs of vertices. + * beginShape(LINES); + * + * // Add vertices. + * vertex(30, 20); + * vertex(85, 20); + * vertex(85, 75); + * vertex(30, 75); + * + * // Stop drawing the shape. + * endShape(); + * + * describe('Two horizontal black lines on a gray background.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Style the shape. + * noFill(); + * + * // Start drawing the shape. + * beginShape(); + * + * // Add vertices. + * vertex(30, 20); + * vertex(85, 20); + * vertex(85, 75); + * vertex(30, 75); + * + * // Stop drawing the shape. + * endShape(); + * + * describe('Three black lines form a sideways U shape on a gray background.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Style the shape. + * noFill(); + * + * // Start drawing the shape. + * beginShape(); + * + * // Add vertices. + * vertex(30, 20); + * vertex(85, 20); + * vertex(85, 75); + * vertex(30, 75); + * + * // Stop drawing the shape. + * // Connect the first and last vertices. + * endShape(CLOSE); + * + * describe('A black outline of a square drawn on a gray background.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Start drawing the shape. + * // Draw a series of triangles. + * beginShape(TRIANGLES); + * + * // Left triangle. + * vertex(30, 75); + * vertex(40, 20); + * vertex(50, 75); + * + * // Right triangle. + * vertex(60, 20); + * vertex(70, 75); + * vertex(80, 20); + * + * // Stop drawing the shape. + * endShape(); + * + * describe('Two white triangles drawn on a gray background.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Start drawing the shape. + * // Draw a series of triangles. + * beginShape(TRIANGLE_STRIP); + * + * // Add vertices. + * vertex(30, 75); + * vertex(40, 20); + * vertex(50, 75); + * vertex(60, 20); + * vertex(70, 75); + * vertex(80, 20); + * vertex(90, 75); + * + * // Stop drawing the shape. + * endShape(); + * + * describe('Five white triangles that are interleaved drawn on a gray background.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Start drawing the shape. + * // Draw a series of triangles that share their first vertex. + * beginShape(TRIANGLE_FAN); + * + * // Add vertices. + * vertex(57.5, 50); + * vertex(57.5, 15); + * vertex(92, 50); + * vertex(57.5, 85); + * vertex(22, 50); + * vertex(57.5, 15); + * + * // Stop drawing the shape. + * endShape(); + * + * describe('Four white triangles form a square are drawn on a gray background.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Start drawing the shape. + * // Draw a series of quadrilaterals. + * beginShape(QUADS); + * + * // Left rectangle. + * vertex(30, 20); + * vertex(30, 75); + * vertex(50, 75); + * vertex(50, 20); + * + * // Right rectangle. + * vertex(65, 20); + * vertex(65, 75); + * vertex(85, 75); + * vertex(85, 20); + * + * // Stop drawing the shape. + * endShape(); + * + * describe('Two white rectangles drawn on a gray background.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Start drawing the shape. + * // Draw a series of quadrilaterals. + * beginShape(QUAD_STRIP); + * + * // Add vertices. + * vertex(30, 20); + * vertex(30, 75); + * vertex(50, 20); + * vertex(50, 75); + * vertex(65, 20); + * vertex(65, 75); + * vertex(85, 20); + * vertex(85, 75); + * + * // Stop drawing the shape. + * endShape(); + * + * describe('Three white rectangles that share edges are drawn on a gray background.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * background(200); + * + * // Start drawing the shape. + * // Draw a series of quadrilaterals. + * beginShape(PATH); + * + * // Add the vertices. + * vertex(-30, -30, 0); + * vertex(30, -30, 0); + * vertex(30, -10, 0); + * vertex(-10, -10, 0); + * vertex(-10, 10, 0); + * vertex(30, 10, 0); + * vertex(30, 30, 0); + * vertex(-30, 30, 0); + * + * // Stop drawing the shape. + * // Connect the first and last vertices. + * endShape(CLOSE); + * + * describe('A blocky C shape drawn in white on a gray background.'); + * } + * + *
+ * + *
+ * + * // Click and drag with the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A blocky C shape drawn in red, blue, and green on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Start drawing the shape. + * // Draw a series of quadrilaterals. + * beginShape(PATH); + * + * // Add the vertices. + * fill('red'); + * stroke('red'); + * vertex(-30, -30, 0); + * vertex(30, -30, 0); + * vertex(30, -10, 0); + * fill('green'); + * stroke('green'); + * vertex(-10, -10, 0); + * vertex(-10, 10, 0); + * vertex(30, 10, 0); + * fill('blue'); + * stroke('blue'); + * vertex(30, 30, 0); + * vertex(-30, 30, 0); + * + * // Stop drawing the shape. + * // Connect the first and last vertices. + * endShape(CLOSE); + * } + * + *
+ */ + fn.beginShape = function(kind) { + // p5._validateParameters('beginShape', arguments); + this._renderer.beginShape(...arguments); + }; + + /** + * @method bezierOrder + * @returns {Number} The current bezier order. + */ + /** + * @method bezierOrder + * @param {Number} order The new order to set. + */ + fn.bezierOrder = function(order) { + return this._renderer.bezierOrder(order); + }; + + /** + * Adds a Bézier curve segment to a custom shape. + * + * `bezierVertex()` adds a curved segment to custom shapes. The Bézier curves + * it creates are defined like those made by the + * bezier() function. `bezierVertex()` must be + * called between the + * beginShape() and + * endShape() functions. The curved segment uses + * the previous vertex as the first anchor point, so there must be at least + * one call to vertex() before `bezierVertex()` can + * be used. + * + * The first four parameters, `x2`, `y2`, `x3`, and `y3`, set the curve’s two + * control points. The control points "pull" the curve towards them. + * + * The fifth and sixth parameters, `x4`, and `y4`, set the last anchor point. + * The last anchor point is where the curve ends. + * + * Bézier curves can also be drawn in 3D using WebGL mode. The 3D version of + * `bezierVertex()` has eight arguments because each point has x-, y-, and + * z-coordinates. + * + * Note: `bezierVertex()` won’t work when an argument is passed to + * beginShape(). + * + * @method bezierVertex + * @param {Number} x x-coordinate of the first control point. + * @param {Number} y y-coordinate of the first control point. + * @param {Number} [u] + * @param {Number} [v] + * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Style the shape. + * noFill(); + * + * // Start drawing the shape. + * beginShape(); + * + * // Add the first anchor point. + * vertex(30, 20); + * + * // Add the Bézier vertex. + * bezierVertex(80, 0, 80, 75, 30, 75); + * + * // Stop drawing the shape. + * endShape(); + * + * describe('A black C curve on a gray background.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Draw the anchor points in black. + * stroke(0); + * strokeWeight(5); + * point(30, 20); + * point(30, 75); + * + * // Draw the control points in red. + * stroke(255, 0, 0); + * point(80, 0); + * point(80, 75); + * + * // Style the shape. + * noFill(); + * stroke(0); + * strokeWeight(1); + * + * // Start drawing the shape. + * beginShape(); + * + * // Add the first anchor point. + * vertex(30, 20); + * + * // Add the Bézier vertex. + * bezierVertex(80, 0, 80, 75, 30, 75); + * + * // Stop drawing the shape. + * endShape(); + * + * // Draw red lines from the anchor points to the control points. + * stroke(255, 0, 0); + * line(30, 20, 80, 0); + * line(30, 75, 80, 75); + * + * describe( + * 'A gray square with three curves. A black curve has two straight, red lines that extend from its ends. The endpoints of all the curves are marked with dots.' + * ); + * } + * + *
+ * + *
+ * + * // Click the mouse near the red dot in the top-right corner + * // and drag to change the curve's shape. + * + * let x2 = 80; + * let y2 = 0; + * let isChanging = false; + * + * function setup() { + * createCanvas(100, 100); + * + * describe( + * 'A gray square with three curves. A black curve has two straight, red lines that extend from its ends. The endpoints of all the curves are marked with dots.' + * ); + * } + * + * function draw() { + * background(200); + * + * // Draw the anchor points in black. + * stroke(0); + * strokeWeight(5); + * point(30, 20); + * point(30, 75); + * + * // Draw the control points in red. + * stroke(255, 0, 0); + * point(x2, y2); + * point(80, 75); + * + * // Style the shape. + * noFill(); + * stroke(0); + * strokeWeight(1); + * + * // Start drawing the shape. + * beginShape(); + * + * // Add the first anchor point. + * vertex(30, 20); + * + * // Add the Bézier vertex. + * bezierVertex(x2, y2, 80, 75, 30, 75); + * + * // Stop drawing the shape. + * endShape(); + * + * // Draw red lines from the anchor points to the control points. + * stroke(255, 0, 0); + * line(30, 20, x2, y2); + * line(30, 75, 80, 75); + * } + * + * // Start changing the first control point if the user clicks near it. + * function mousePressed() { + * if (dist(mouseX, mouseY, x2, y2) < 20) { + * isChanging = true; + * } + * } + * + * // Stop changing the first control point when the user releases the mouse. + * function mouseReleased() { + * isChanging = false; + * } + * + * // Update the first control point while the user drags the mouse. + * function mouseDragged() { + * if (isChanging === true) { + * x2 = mouseX; + * y2 = mouseY; + * } + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Start drawing the shape. + * beginShape(); + * + * // Add the first anchor point. + * vertex(30, 20); + * + * // Add the Bézier vertices. + * bezierVertex(80, 0, 80, 75, 30, 75); + * bezierVertex(50, 80, 60, 25, 30, 20); + * + * // Stop drawing the shape. + * endShape(); + * + * describe('A crescent moon shape drawn in white on a gray background.'); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A crescent moon shape drawn in white on a blue background. When the user drags the mouse, the scene rotates and a second moon is revealed.'); + * } + * + * function draw() { + * background('midnightblue'); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Style the moons. + * noStroke(); + * fill('lemonchiffon'); + * + * // Draw the first moon. + * beginShape(); + * vertex(-20, -30, 0); + * bezierVertex(30, -50, 0, 30, 25, 0, -20, 25, 0); + * bezierVertex(0, 30, 0, 10, -25, 0, -20, -30, 0); + * endShape(); + * + * // Draw the second moon. + * beginShape(); + * vertex(-20, -30, -20); + * bezierVertex(30, -50, -20, 30, 25, -20, -20, 25, -20); + * bezierVertex(0, 30, -20, 10, -25, -20, -20, -30, -20); + * endShape(); + * } + * + *
+ */ + + /** + * @method bezierVertex + * @param {Number} x + * @param {Number} y + * @param {Number} z + * @param {Number} [u] + * @param {Number} [v] + */ + fn.bezierVertex = function(...args) { + this._renderer.bezierVertex(...args); + }; + + /** + * Stops creating a hole within a flat shape. + * + * The beginContour() and `endContour()` + * functions allow for creating negative space within custom shapes that are + * flat. beginContour() begins adding vertices + * to a negative space and `endContour()` stops adding them. + * beginContour() and `endContour()` must be + * called between beginShape() and + * endShape(). + * + * Transformations such as translate(), + * rotate(), and scale() + * don't work between beginContour() and + * `endContour()`. It's also not possible to use other shapes, such as + * ellipse() or rect(), + * between beginContour() and `endContour()`. + * + * Note: The vertices that define a negative space must "wind" in the opposite + * direction from the outer shape. First, draw vertices for the outer shape + * clockwise order. Then, draw vertices for the negative space in + * counter-clockwise order. + * + * @method endContour + * @param {OPEN|CLOSE} [mode=OPEN] + * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Start drawing the shape. + * beginShape(); + * + * // Exterior vertices, clockwise winding. + * vertex(10, 10); + * vertex(90, 10); + * vertex(90, 90); + * vertex(10, 90); + * + * // Interior vertices, counter-clockwise winding. + * beginContour(); + * vertex(30, 30); + * vertex(30, 70); + * vertex(70, 70); + * vertex(70, 30); + * endContour(); + * + * // Stop drawing the shape. + * endShape(CLOSE); + * + * describe('A white square with a square hole in its center drawn on a gray background.'); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white square with a square hole in its center drawn on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Start drawing the shape. + * beginShape(); + * + * // Exterior vertices, clockwise winding. + * vertex(-40, -40); + * vertex(40, -40); + * vertex(40, 40); + * vertex(-40, 40); + * + * // Interior vertices, counter-clockwise winding. + * beginContour(); + * vertex(-20, -20); + * vertex(-20, 20); + * vertex(20, 20); + * vertex(20, -20); + * endContour(); + * + * // Stop drawing the shape. + * endShape(CLOSE); + * } + * + *
+ */ + fn.endContour = function(mode = constants.OPEN) { + this._renderer.endContour(mode); + }; + + /** + * Begins adding vertices to a custom shape. + * + * The beginShape() and `endShape()` functions + * allow for creating custom shapes in 2D or 3D. + * beginShape() begins adding vertices to a + * custom shape and `endShape()` stops adding them. + * + * The first parameter, `mode`, is optional. By default, the first and last + * vertices of a shape aren't connected. If the constant `CLOSE` is passed, as + * in `endShape(CLOSE)`, then the first and last vertices will be connected. + * + * The second parameter, `count`, is also optional. In WebGL mode, it’s more + * efficient to draw many copies of the same shape using a technique called + * instancing. + * The `count` parameter tells WebGL mode how many copies to draw. For + * example, calling `endShape(CLOSE, 400)` after drawing a custom shape will + * make it efficient to draw 400 copies. This feature requires + * writing a custom shader. + * + * After calling beginShape(), shapes can be + * built by calling vertex(), + * bezierVertex(), + * quadraticVertex(), and/or + * splineVertex(). Calling + * `endShape()` will stop adding vertices to the + * shape. Each shape will be outlined with the current stroke color and filled + * with the current fill color. + * + * Transformations such as translate(), + * rotate(), and + * scale() don't work between + * beginShape() and `endShape()`. It's also not + * possible to use other shapes, such as ellipse() or + * rect(), between + * beginShape() and `endShape()`. + * + * @method endShape + * @param {CLOSE} [mode] use CLOSE to close the shape + * @param {Integer} [count] number of times you want to draw/instance the shape (for WebGL mode). + * @chainable + * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Style the shapes. + * noFill(); + * + * // Left triangle. + * beginShape(); + * vertex(20, 20); + * vertex(45, 20); + * vertex(45, 80); + * endShape(CLOSE); + * + * // Right triangle. + * beginShape(); + * vertex(50, 20); + * vertex(75, 20); + * vertex(75, 80); + * endShape(); + * + * describe( + * 'Two sets of black lines drawn on a gray background. The three lines on the left form a right triangle. The two lines on the right form a right angle.' + * ); + * } + * + *
+ * + *
+ * + * // Note: A "uniform" is a global variable within a shader program. + * + * // Create a string with the vertex shader program. + * // The vertex shader is called for each vertex. + * let vertSrc = `#version 300 es + * + * precision mediump float; + * + * in vec3 aPosition; + * flat out int instanceID; + * + * uniform mat4 uModelViewMatrix; + * uniform mat4 uProjectionMatrix; + * + * void main() { + * + * // Copy the instance ID to the fragment shader. + * instanceID = gl_InstanceID; + * vec4 positionVec4 = vec4(aPosition, 1.0); + * + * // gl_InstanceID represents a numeric value for each instance. + * // Using gl_InstanceID allows us to move each instance separately. + * // Here we move each instance horizontally by ID * 23. + * float xOffset = float(gl_InstanceID) * 23.0; + * + * // Apply the offset to the final position. + * gl_Position = uProjectionMatrix * uModelViewMatrix * (positionVec4 - + * vec4(xOffset, 0.0, 0.0, 0.0)); + * } + * `; + * + * // Create a string with the fragment shader program. + * // The fragment shader is called for each pixel. + * let fragSrc = `#version 300 es + * + * precision mediump float; + * + * out vec4 outColor; + * flat in int instanceID; + * uniform float numInstances; + * + * void main() { + * vec4 red = vec4(1.0, 0.0, 0.0, 1.0); + * vec4 blue = vec4(0.0, 0.0, 1.0, 1.0); + * + * // Normalize the instance ID. + * float normId = float(instanceID) / numInstances; + * + * // Mix between two colors using the normalized instance ID. + * outColor = mix(red, blue, normId); + * } + * `; + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Create a p5.Shader object. + * let myShader = createShader(vertSrc, fragSrc); + * + * background(220); + * + * // Compile and apply the p5.Shader. + * shader(myShader); + * + * // Set the numInstances uniform. + * myShader.setUniform('numInstances', 4); + * + * // Translate the origin to help align the drawing. + * translate(25, -10); + * + * // Style the shapes. + * noStroke(); + * + * // Draw the shapes. + * beginShape(); + * vertex(0, 0); + * vertex(0, 20); + * vertex(20, 20); + * vertex(20, 0); + * vertex(0, 0); + * endShape(CLOSE, 4); + * + * describe('A row of four squares. Their colors transition from purple on the left to red on the right'); + * } + * + *
+ */ + fn.endShape = function(mode, count = 1) { + // p5._validateParameters('endShape', arguments); + if (count < 1) { + console.log('🌸 p5.js says: You can not have less than one instance'); + count = 1; + } + + this._renderer.endShape(mode, count); + }; + + /** + * Sets the normal vector for vertices in a custom 3D shape. + * + * 3D shapes created with beginShape() and + * endShape() are made by connecting sets of + * points called vertices. Each vertex added with + * vertex() has a normal vector that points away + * from it. The normal vector controls how light reflects off the shape. + * + * `normal()` can be called two ways with different parameters to define the + * normal vector's components. + * + * The first way to call `normal()` has three parameters, `x`, `y`, and `z`. + * If `Number`s are passed, as in `normal(1, 2, 3)`, they set the x-, y-, and + * z-components of the normal vector. + * + * The second way to call `normal()` has one parameter, `vector`. If a + * p5.Vector object is passed, as in + * `normal(myVector)`, its components will be used to set the normal vector. + * + * `normal()` changes the normal vector of vertices added to a custom shape + * with vertex(). `normal()` must be called between + * the beginShape() and + * endShape() functions, just like + * vertex(). The normal vector set by calling + * `normal()` will affect all following vertices until `normal()` is called + * again: + * + * ```js + * beginShape(); + * + * // Set the vertex normal. + * normal(-0.4, -0.4, 0.8); + * + * // Add a vertex. + * vertex(-30, -30, 0); + * + * // Set the vertex normal. + * normal(0, 0, 1); + * + * // Add vertices. + * vertex(30, -30, 0); + * vertex(30, 30, 0); + * + * // Set the vertex normal. + * normal(0.4, -0.4, 0.8); + * + * // Add a vertex. + * vertex(-30, 30, 0); + * + * endShape(); + * ``` + * + * @method normal + * @param {p5.Vector} vector vertex normal as a p5.Vector object. + * @chainable + * + * @example + *
+ * + * // Click the and drag the mouse to view the scene from a different angle. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe( + * 'A colorful square on a black background. The square changes color and rotates when the user drags the mouse. Parts of its surface reflect light in different directions.' + * ); + * } + * + * function draw() { + * background(0); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Style the shape. + * normalMaterial(); + * noStroke(); + * + * // Draw the shape. + * beginShape(); + * vertex(-30, -30, 0); + * vertex(30, -30, 0); + * vertex(30, 30, 0); + * vertex(-30, 30, 0); + * endShape(); + * } + * + *
+ * + *
+ * + * // Click the and drag the mouse to view the scene from a different angle. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe( + * 'A colorful square on a black background. The square changes color and rotates when the user drags the mouse. Parts of its surface reflect light in different directions.' + * ); + * } + * + * function draw() { + * background(0); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Style the shape. + * normalMaterial(); + * noStroke(); + * + * // Draw the shape. + * // Use normal() to set vertex normals. + * beginShape(); + * normal(-0.4, -0.4, 0.8); + * vertex(-30, -30, 0); + * + * normal(0, 0, 1); + * vertex(30, -30, 0); + * vertex(30, 30, 0); + * + * normal(0.4, -0.4, 0.8); + * vertex(-30, 30, 0); + * endShape(); + * } + * + *
+ * + *
+ * + * // Click the and drag the mouse to view the scene from a different angle. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe( + * 'A colorful square on a black background. The square changes color and rotates when the user drags the mouse. Parts of its surface reflect light in different directions.' + * ); + * } + * + * function draw() { + * background(0); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Style the shape. + * normalMaterial(); + * noStroke(); + * + * // Create p5.Vector objects. + * let n1 = createVector(-0.4, -0.4, 0.8); + * let n2 = createVector(0, 0, 1); + * let n3 = createVector(0.4, -0.4, 0.8); + * + * // Draw the shape. + * // Use normal() to set vertex normals. + * beginShape(); + * normal(n1); + * vertex(-30, -30, 0); + * + * normal(n2); + * vertex(30, -30, 0); + * vertex(30, 30, 0); + * + * normal(n3); + * vertex(-30, 30, 0); + * endShape(); + * } + * + *
+ */ + /** - * @method bezierOrder - * @returns {Number} The current bezier order. + * @method normal + * @param {Number} x x-component of the vertex normal. + * @param {Number} y y-component of the vertex normal. + * @param {Number} z z-component of the vertex normal. + * @chainable */ + fn.normal = function(x, y, z) { + this._assert3d('normal'); + // p5._validateParameters('normal', arguments); + this._renderer.normal(...arguments); + + return this; + }; + /** - * @method bezierOrder - * @param {Number} order The new order to set. + * @method splineProperties + * @returns {Object} The current spline properties. + */ + /** + * @method splineProperties + * @param {Object} An object containing key-value pairs to set. + */ + fn.splineProperties = function(values) { + return this._renderer.splineProperties(values); + }; + + /** + * @method splineProperty + * @param {String} property + * @returns value The current value for the given property. + */ + /** + * @method splineProperty + * @param {String} property + * @param value Value to set the given property to. + */ + fn.splineProperty = function(property, value) { + return this._renderer.splineProperty(property, value); + }; + + /** + * Adds a spline segment to a custom shape. + * + * NOTE: THESE DOCS ARE BASED ON THE OLD `curveVertex()` DOCS; UPDATES MAY STILL + * BE REQUIRED. + * + * `splineVertex()` adds a curved segment to custom shapes. The spline curves + * it creates are defined like those made by the + * curve() function. `splineVertex()` must be called + * between the beginShape() and + * endShape() functions. + * + * Spline curves can form shapes and curves that slope gently. They’re like + * cables that are attached to a set of points. Splines are defined by two + * anchor points and two control points. `splineVertex()` must be called at + * least four times between + * beginShape() and + * endShape() in order to draw a curve: + * + * ```js + * beginShape(); + * + * // Add the first control point. + * splineVertex(84, 91); + * + * // Add the anchor points to draw between. + * splineVertex(68, 19); + * splineVertex(21, 17); + * + * // Add the second control point. + * splineVertex(32, 91); + * + * endShape(); + * ``` + * + * The code snippet above would only draw the curve between the anchor points, + * similar to the curve() function. The segments + * between the control and anchor points can be drawn by calling + * `splineVertex()` with the coordinates of the control points: + * + * ```js + * beginShape(); + * + * // Add the first control point and draw a segment to it. + * splineVertex(84, 91); + * splineVertex(84, 91); + * + * // Add the anchor points to draw between. + * splineVertex(68, 19); + * splineVertex(21, 17); + * + * // Add the second control point. + * splineVertex(32, 91); + * + * // Uncomment the next line to draw the segment to the second control point. + * // splineVertex(32, 91); + * + * endShape(); + * ``` + * + * The first two parameters, `x` and `y`, set the vertex’s location. For + * example, calling `splineVertex(10, 10)` adds a point to the curve at + * `(10, 10)`. + * + * Spline curves can also be drawn in 3D using WebGL mode. The 3D version of + * `splineVertex()` has three arguments because each point has x-, y-, and + * z-coordinates. By default, the vertex’s z-coordinate is set to 0. + * + * Note: `splineVertex()` won’t work when an argument is passed to + * beginShape(). + * + * @method splineVertex + * @param {Number} x + * @param {Number} y + * @param {Number} [u=0] + * @param {Number} [v=0] + * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Style the shape. + * noFill(); + * strokeWeight(1); + * + * // Start drawing the shape. + * beginShape(); + * + * // Add the first control point. + * splineVertex(32, 91); + * + * // Add the anchor points. + * splineVertex(21, 17); + * splineVertex(68, 19); + * + * // Add the second control point. + * splineVertex(84, 91); + * + * // Stop drawing the shape. + * endShape(); + * + * // Style the anchor and control points. + * strokeWeight(5); + * + * // Draw the anchor points in black. + * stroke(0); + * point(21, 17); + * point(68, 19); + * + * // Draw the control points in red. + * stroke(255, 0, 0); + * point(32, 91); + * point(84, 91); + * + * describe( + * 'A black curve drawn on a gray background. The curve has black dots at its ends. Two red dots appear near the bottom of the canvas.' + * ); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Style the shape. + * noFill(); + * strokeWeight(1); + * + * // Start drawing the shape. + * beginShape(); + * + * // Add the first control point and draw a segment to it. + * splineVertex(32, 91); + * splineVertex(32, 91); + * + * // Add the anchor points. + * splineVertex(21, 17); + * splineVertex(68, 19); + * + * // Add the second control point. + * splineVertex(84, 91); + * + * // Stop drawing the shape. + * endShape(); + * + * // Style the anchor and control points. + * strokeWeight(5); + * + * // Draw the anchor points in black. + * stroke(0); + * point(21, 17); + * point(68, 19); + * + * // Draw the control points in red. + * stroke(255, 0, 0); + * point(32, 91); + * point(84, 91); + * + * describe( + * 'A black curve drawn on a gray background. The curve passes through one red dot and two black dots. Another red dot appears near the bottom of the canvas.' + * ); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Style the shape. + * noFill(); + * strokeWeight(1); + * + * // Start drawing the shape. + * beginShape(); + * + * // Add the first control point and draw a segment to it. + * splineVertex(32, 91); + * splineVertex(32, 91); + * + * // Add the anchor points. + * splineVertex(21, 17); + * splineVertex(68, 19); + * + * // Add the second control point and draw a segment to it. + * splineVertex(84, 91); + * splineVertex(84, 91); + * + * // Stop drawing the shape. + * endShape(); + * + * // Style the anchor and control points. + * strokeWeight(5); + * + * // Draw the anchor points in black. + * stroke(0); + * point(21, 17); + * point(68, 19); + * + * // Draw the control points in red. + * stroke(255, 0, 0); + * point(32, 91); + * point(84, 91); + * + * describe( + * 'A black U curve drawn upside down on a gray background. The curve passes from one red dot through two black dots and ends at another red dot.' + * ); + * } + * + *
+ * + *
+ * + * // Click the mouse near the red dot in the bottom-left corner + * // and drag to change the curve's shape. + * + * let x1 = 32; + * let y1 = 91; + * let isChanging = false; + * + * function setup() { + * createCanvas(100, 100); + * + * describe( + * 'A black U curve drawn upside down on a gray background. The curve passes from one red dot through two black dots and ends at another red dot.' + * ); + * } + * + * function draw() { + * background(200); + * + * // Style the shape. + * noFill(); + * stroke(0); + * strokeWeight(1); + * + * // Start drawing the shape. + * beginShape(); + * + * // Add the first control point and draw a segment to it. + * splineVertex(x1, y1); + * splineVertex(x1, y1); + * + * // Add the anchor points. + * splineVertex(21, 17); + * splineVertex(68, 19); + * + * // Add the second control point and draw a segment to it. + * splineVertex(84, 91); + * splineVertex(84, 91); + * + * // Stop drawing the shape. + * endShape(); + * + * // Style the anchor and control points. + * strokeWeight(5); + * + * // Draw the anchor points in black. + * stroke(0); + * point(21, 17); + * point(68, 19); + * + * // Draw the control points in red. + * stroke(255, 0, 0); + * point(x1, y1); + * point(84, 91); + * } + * + * // Start changing the first control point if the user clicks near it. + * function mousePressed() { + * if (dist(mouseX, mouseY, x1, y1) < 20) { + * isChanging = true; + * } + * } + * + * // Stop changing the first control point when the user releases the mouse. + * function mouseReleased() { + * isChanging = false; + * } + * + * // Update the first control point while the user drags the mouse. + * function mouseDragged() { + * if (isChanging === true) { + * x1 = mouseX; + * y1 = mouseY; + * } + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Start drawing the shape. + * beginShape(); + * + * // Add the first control point and draw a segment to it. + * splineVertex(32, 91); + * splineVertex(32, 91); + * + * // Add the anchor points. + * splineVertex(21, 17); + * splineVertex(68, 19); + * + * // Add the second control point. + * splineVertex(84, 91); + * splineVertex(84, 91); + * + * // Stop drawing the shape. + * endShape(); + * + * describe('A ghost shape drawn in white on a gray background.'); + * } + * + *
*/ - fn.bezierOrder = function(order) { - return this._renderer.bezierOrder(order); - }; - /** - * @method splineVertex - * @param {Number} x - * @param {Number} y - * @param {Number} [u=0] - * @param {Number} [v=0] - */ /** * @method splineVertex * @param {Number} x @@ -1609,7 +3177,54 @@ function customShapes(p5, fn) { * @param {Number} z * @param {Number} [u=0] * @param {Number} [v=0] + * + * @example + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A ghost shape drawn in white on a blue background. When the user drags the mouse, the scene rotates to reveal the outline of a second ghost.'); + * } + * + * function draw() { + * background('midnightblue'); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Draw the first ghost. + * noStroke(); + * fill('ghostwhite'); + * + * beginShape(); + * splineVertex(-28, 41, 0); + * splineVertex(-28, 41, 0); + * splineVertex(-29, -33, 0); + * splineVertex(18, -31, 0); + * splineVertex(34, 41, 0); + * splineVertex(34, 41, 0); + * endShape(); + * + * // Draw the second ghost. + * noFill(); + * stroke('ghostwhite'); + * + * beginShape(); + * splineVertex(-28, 41, -20); + * splineVertex(-28, 41, -20); + * splineVertex(-29, -33, -20); + * splineVertex(18, -31, -20); + * splineVertex(34, 41, -20); + * splineVertex(34, 41, -20); + * endShape(); + * } + * + *
*/ + fn.splineVertex = function(...args) { let x = 0, y = 0, z = 0, u = 0, v = 0; if (args.length === 2) { @@ -1624,32 +3239,6 @@ function customShapes(p5, fn) { this._renderer.splineVertex(x, y, z, u, v); }; - /** - * @method splineProperty - * @param {String} property - * @returns value The current value for the given property. - */ - /** - * @method splineProperty - * @param {String} property - * @param value Value to set the given property to. - */ - fn.splineProperty = function(property, value) { - return this._renderer.splineProperty(property, value); - }; - - /** - * @method splineProperties - * @returns {Object} The current spline properties. - */ - /** - * @method splineProperties - * @param {Object} An object containing key-value pairs to set. - */ - fn.splineProperties = function(values) { - return this._renderer.splineProperties(values); - }; - /** * Adds a vertex to a custom shape. * @@ -1857,207 +3446,177 @@ function customShapes(p5, fn) { }; /** - * Begins creating a hole within a flat shape. + * Sets the shader's vertex property or attribute variables. * - * The `beginContour()` and endContour() - * functions allow for creating negative space within custom shapes that are - * flat. `beginContour()` begins adding vertices to a negative space and - * endContour() stops adding them. - * `beginContour()` and endContour() must be - * called between beginShape() and + * A vertex property, or vertex attribute, is a variable belonging to a vertex in a shader. p5.js provides some + * default properties, such as `aPosition`, `aNormal`, `aVertexColor`, etc. These are + * set using vertex(), normal() + * and fill() respectively. Custom properties can also + * be defined within beginShape() and * endShape(). * - * Transformations such as translate(), - * rotate(), and scale() - * don't work between `beginContour()` and - * endContour(). It's also not possible to use - * other shapes, such as ellipse() or - * rect(), between `beginContour()` and - * endContour(). - * - * Note: The vertices that define a negative space must "wind" in the opposite - * direction from the outer shape. First, draw vertices for the outer shape - * clockwise order. Then, draw vertices for the negative space in - * counter-clockwise order. - * - * @method beginContour - * - * @example - *
- * - * function setup() { - * createCanvas(100, 100); - * - * background(200); - * - * // Start drawing the shape. - * beginShape(); - * - * // Exterior vertices, clockwise winding. - * vertex(10, 10); - * vertex(90, 10); - * vertex(90, 90); - * vertex(10, 90); + * The first parameter, `propertyName`, is a string with the property's name. + * This is the same variable name which should be declared in the shader, such as + * `in vec3 aProperty`, similar to .`setUniform()`. * - * // Interior vertices, counter-clockwise winding. - * beginContour(); - * vertex(30, 30); - * vertex(30, 70); - * vertex(70, 70); - * vertex(70, 30); - * endContour(); + * The second parameter, `data`, is the value assigned to the shader variable. This + * value will be applied to subsequent vertices created with + * vertex(). It can be a Number or an array of numbers, + * and in the shader program the type can be declared according to the WebGL + * specification. Common types include `float`, `vec2`, `vec3`, `vec4` or matrices. * - * // Stop drawing the shape. - * endShape(CLOSE); + * See also the vertexProperty() method on + * Geometry objects. * - * describe('A white square with a square hole in its center drawn on a gray background.'); - * } - * - *
+ * @method vertexProperty + * @for p5 + * @param {String} attributeName the name of the vertex attribute. + * @param {Number|Number[]} data the data tied to the vertex attribute. * + * @example *
* - * // Click and drag the mouse to view the scene from different angles. - * - * function setup() { + * const vertSrc = `#version 300 es + * precision mediump float; + * uniform mat4 uModelViewMatrix; + * uniform mat4 uProjectionMatrix; + * + * in vec3 aPosition; + * in vec2 aOffset; + * + * void main(){ + * vec4 positionVec4 = vec4(aPosition.xyz, 1.0); + * positionVec4.xy += aOffset; + * gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4; + * } + * `; + * + * const fragSrc = `#version 300 es + * precision mediump float; + * out vec4 outColor; + * void main(){ + * outColor = vec4(0.0, 1.0, 1.0, 1.0); + * } + * `; + * + * function setup(){ * createCanvas(100, 100, WEBGL); * - * describe('A white square with a square hole in its center drawn on a gray background.'); - * } - * - * function draw() { - * background(200); - * - * // Enable orbiting with the mouse. - * orbitControl(); - * - * // Start drawing the shape. - * beginShape(); - * - * // Exterior vertices, clockwise winding. - * vertex(-40, -40); - * vertex(40, -40); - * vertex(40, 40); - * vertex(-40, 40); - * - * // Interior vertices, counter-clockwise winding. - * beginContour(); - * vertex(-20, -20); - * vertex(-20, 20); - * vertex(20, 20); - * vertex(20, -20); - * endContour(); + * // Create and use the custom shader. + * const myShader = createShader(vertSrc, fragSrc); + * shader(myShader); * - * // Stop drawing the shape. - * endShape(CLOSE); + * describe('A wobbly, cyan circle on a gray background.'); * } - * - *
- */ - fn.beginContour = function(kind) { - this._renderer.beginContour(kind); - }; - - /** - * Stops creating a hole within a flat shape. - * - * The beginContour() and `endContour()` - * functions allow for creating negative space within custom shapes that are - * flat. beginContour() begins adding vertices - * to a negative space and `endContour()` stops adding them. - * beginContour() and `endContour()` must be - * called between beginShape() and - * endShape(). - * - * Transformations such as translate(), - * rotate(), and scale() - * don't work between beginContour() and - * `endContour()`. It's also not possible to use other shapes, such as - * ellipse() or rect(), - * between beginContour() and `endContour()`. - * - * Note: The vertices that define a negative space must "wind" in the opposite - * direction from the outer shape. First, draw vertices for the outer shape - * clockwise order. Then, draw vertices for the negative space in - * counter-clockwise order. - * - * @method endContour - * @param {OPEN|CLOSE} [mode=OPEN] - * - * @example - *
- * - * function setup() { - * createCanvas(100, 100); * - * background(200); + * function draw(){ + * // Set the styles + * background(125); + * noStroke(); * - * // Start drawing the shape. + * // Draw the circle. * beginShape(); - * - * // Exterior vertices, clockwise winding. - * vertex(10, 10); - * vertex(90, 10); - * vertex(90, 90); - * vertex(10, 90); - * - * // Interior vertices, counter-clockwise winding. - * beginContour(); - * vertex(30, 30); - * vertex(30, 70); - * vertex(70, 70); - * vertex(70, 30); - * endContour(); - * - * // Stop drawing the shape. + * for (let i = 0; i < 30; i++){ + * const x = 40 * cos(i/30 * TWO_PI); + * const y = 40 * sin(i/30 * TWO_PI); + * + * // Apply some noise to the coordinates. + * const xOff = 10 * noise(x + millis()/1000) - 5; + * const yOff = 10 * noise(y + millis()/1000) - 5; + * + * // Apply these noise values to the following vertex. + * vertexProperty('aOffset', [xOff, yOff]); + * vertex(x, y); + * } * endShape(CLOSE); - * - * describe('A white square with a square hole in its center drawn on a gray background.'); * } * *
* *
* - * // Click and drag the mouse to view the scene from different angles. - * - * function setup() { + * let myShader; + * const cols = 10; + * const rows = 10; + * const cellSize = 6; + * + * const vertSrc = `#version 300 es + * precision mediump float; + * uniform mat4 uProjectionMatrix; + * uniform mat4 uModelViewMatrix; + * + * in vec3 aPosition; + * in vec3 aNormal; + * in vec3 aVertexColor; + * in float aDistance; + * + * out vec3 vVertexColor; + * + * void main(){ + * vec4 positionVec4 = vec4(aPosition, 1.0); + * positionVec4.xyz += aDistance * aNormal * 2.0;; + * vVertexColor = aVertexColor; + * gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4; + * } + * `; + * + * const fragSrc = `#version 300 es + * precision mediump float; + * + * in vec3 vVertexColor; + * out vec4 outColor; + * + * void main(){ + * outColor = vec4(vVertexColor, 1.0); + * } + * `; + * + * function setup(){ * createCanvas(100, 100, WEBGL); * - * describe('A white square with a square hole in its center drawn on a gray background.'); + * // Create and apply the custom shader. + * myShader = createShader(vertSrc, fragSrc); + * shader(myShader); + * noStroke(); + * describe('A blue grid, which moves away from the mouse position, on a gray background.'); * } * - * function draw() { + * function draw(){ * background(200); * - * // Enable orbiting with the mouse. - * orbitControl(); + * // Draw the grid in the middle of the screen. + * translate(-cols*cellSize/2, -rows*cellSize/2); + * beginShape(QUADS); + * for (let i = 0; i < cols; i++) { + * for (let j = 0; j < rows; j++) { * - * // Start drawing the shape. - * beginShape(); + * // Calculate the cell position. + * let x = i * cellSize; + * let y = j * cellSize; * - * // Exterior vertices, clockwise winding. - * vertex(-40, -40); - * vertex(40, -40); - * vertex(40, 40); - * vertex(-40, 40); + * fill(j/rows*255, j/cols*255, 255); * - * // Interior vertices, counter-clockwise winding. - * beginContour(); - * vertex(-20, -20); - * vertex(-20, 20); - * vertex(20, 20); - * vertex(20, -20); - * endContour(); + * // Calculate the distance from the corner of each cell to the mouse. + * let distance = dist(x, y, mouseX, mouseY); * - * // Stop drawing the shape. - * endShape(CLOSE); + * // Send the distance to the shader. + * vertexProperty('aDistance', min(distance, 100)); + * + * vertex(x, y); + * vertex(x + cellSize, y); + * vertex(x + cellSize, y + cellSize); + * vertex(x, y + cellSize); + * } + * } + * endShape(); * } * *
*/ - fn.endContour = function(mode = constants.OPEN) { - this._renderer.endContour(mode); + fn.vertexProperty = function(attributeName, data){ + // this._assert3d('vertexProperty'); + // p5._validateParameters('vertexProperty', arguments); + this._renderer.vertexProperty(attributeName, data); }; } diff --git a/src/shape/index.js b/src/shape/index.js index dbc520ff83..df34336403 100644 --- a/src/shape/index.js +++ b/src/shape/index.js @@ -1,13 +1,11 @@ import primitives from './2d_primitives.js'; import attributes from './attributes.js'; import curves from './curves.js'; -import vertex from './vertex.js'; import customShapes from './custom_shapes.js'; export default function(p5){ p5.registerAddon(primitives); p5.registerAddon(attributes); p5.registerAddon(curves); - p5.registerAddon(vertex); p5.registerAddon(customShapes); } \ No newline at end of file diff --git a/src/shape/package.json b/src/shape/package.json new file mode 100644 index 0000000000..459740f59f --- /dev/null +++ b/src/shape/package.json @@ -0,0 +1,6 @@ +{ + "type": "module", + "dependencies": { + "constants.js": "file:../core/constants" + } +} \ No newline at end of file diff --git a/src/shape/vertex.js b/src/shape/vertex.js deleted file mode 100644 index e8e32fe072..0000000000 --- a/src/shape/vertex.js +++ /dev/null @@ -1,1592 +0,0 @@ -/** - * @module Shape - * @submodule Vertex - * @for p5 - * @requires core - * @requires constants - */ - -import * as constants from '../core/constants'; - -function vertex(p5, fn){ - /** - * Begins adding vertices to a custom shape. - * - * The `beginShape()` and endShape() functions - * allow for creating custom shapes in 2D or 3D. `beginShape()` begins adding - * vertices to a custom shape and endShape() stops - * adding them. - * - * The parameter, `kind`, sets the kind of shape to make. The available kinds are: - * - * - `PATH` (the default) to draw shapes by tracing out the path along their edges. - * - `POINTS` to draw a series of points. - * - `LINES` to draw a series of unconnected line segments. - * - `TRIANGLES` to draw a series of separate triangles. - * - `TRIANGLE_FAN` to draw a series of connected triangles sharing the first vertex in a fan-like fashion. - * - `TRIANGLE_STRIP` to draw a series of connected triangles in strip fashion. - * - `QUADS` to draw a series of separate quadrilaterals (quads). - * - `QUAD_STRIP` to draw quad strip using adjacent edges to form the next quad. - * - * After calling `beginShape()`, shapes can be built by calling - * vertex(), - * bezierVertex(), - * bezierVertex(), and/or - * splineVertex(). Calling - * endShape() will stop adding vertices to the - * shape. Each shape will be outlined with the current stroke color and filled - * with the current fill color. - * - * Transformations such as translate(), - * rotate(), and - * scale() don't work between `beginShape()` and - * endShape(). It's also not possible to use - * other shapes, such as ellipse() or - * rect(), between `beginShape()` and - * endShape(). - * - * @method beginShape - * @param {(POINTS|LINES|TRIANGLES|TRIANGLE_FAN|TRIANGLE_STRIP|QUADS|QUAD_STRIP|PATH)} [kind=PATH] either POINTS, LINES, TRIANGLES, TRIANGLE_FAN - * TRIANGLE_STRIP, QUADS, QUAD_STRIP or PATH. Defaults to PATH. - * @chainable - * - * @example - *
- * - * function setup() { - * createCanvas(100, 100); - * - * background(200); - * - * // Start drawing the shape. - * beginShape(); - * - * // Add vertices. - * vertex(30, 20); - * vertex(85, 20); - * vertex(85, 75); - * vertex(30, 75); - * - * // Stop drawing the shape. - * endShape(CLOSE); - * - * describe('A white square on a gray background.'); - * } - * - *
- * - *
- * - * function setup() { - * createCanvas(100, 100); - * - * background(200); - * - * // Start drawing the shape. - * // Only draw the vertices (points). - * beginShape(POINTS); - * - * // Add vertices. - * vertex(30, 20); - * vertex(85, 20); - * vertex(85, 75); - * vertex(30, 75); - * - * // Stop drawing the shape. - * endShape(); - * - * describe('Four black dots that form a square are drawn on a gray background.'); - * } - * - *
- * - *
- * - * function setup() { - * createCanvas(100, 100); - * - * background(200); - * - * // Start drawing the shape. - * // Only draw lines between alternating pairs of vertices. - * beginShape(LINES); - * - * // Add vertices. - * vertex(30, 20); - * vertex(85, 20); - * vertex(85, 75); - * vertex(30, 75); - * - * // Stop drawing the shape. - * endShape(); - * - * describe('Two horizontal black lines on a gray background.'); - * } - * - *
- * - *
- * - * function setup() { - * createCanvas(100, 100); - * - * background(200); - * - * // Style the shape. - * noFill(); - * - * // Start drawing the shape. - * beginShape(); - * - * // Add vertices. - * vertex(30, 20); - * vertex(85, 20); - * vertex(85, 75); - * vertex(30, 75); - * - * // Stop drawing the shape. - * endShape(); - * - * describe('Three black lines form a sideways U shape on a gray background.'); - * } - * - *
- * - *
- * - * function setup() { - * createCanvas(100, 100); - * - * background(200); - * - * // Style the shape. - * noFill(); - * - * // Start drawing the shape. - * beginShape(); - * - * // Add vertices. - * vertex(30, 20); - * vertex(85, 20); - * vertex(85, 75); - * vertex(30, 75); - * - * // Stop drawing the shape. - * // Connect the first and last vertices. - * endShape(CLOSE); - * - * describe('A black outline of a square drawn on a gray background.'); - * } - * - *
- * - *
- * - * function setup() { - * createCanvas(100, 100); - * - * background(200); - * - * // Start drawing the shape. - * // Draw a series of triangles. - * beginShape(TRIANGLES); - * - * // Left triangle. - * vertex(30, 75); - * vertex(40, 20); - * vertex(50, 75); - * - * // Right triangle. - * vertex(60, 20); - * vertex(70, 75); - * vertex(80, 20); - * - * // Stop drawing the shape. - * endShape(); - * - * describe('Two white triangles drawn on a gray background.'); - * } - * - *
- * - *
- * - * function setup() { - * createCanvas(100, 100); - * - * background(200); - * - * // Start drawing the shape. - * // Draw a series of triangles. - * beginShape(TRIANGLE_STRIP); - * - * // Add vertices. - * vertex(30, 75); - * vertex(40, 20); - * vertex(50, 75); - * vertex(60, 20); - * vertex(70, 75); - * vertex(80, 20); - * vertex(90, 75); - * - * // Stop drawing the shape. - * endShape(); - * - * describe('Five white triangles that are interleaved drawn on a gray background.'); - * } - * - *
- * - *
- * - * function setup() { - * createCanvas(100, 100); - * - * background(200); - * - * // Start drawing the shape. - * // Draw a series of triangles that share their first vertex. - * beginShape(TRIANGLE_FAN); - * - * // Add vertices. - * vertex(57.5, 50); - * vertex(57.5, 15); - * vertex(92, 50); - * vertex(57.5, 85); - * vertex(22, 50); - * vertex(57.5, 15); - * - * // Stop drawing the shape. - * endShape(); - * - * describe('Four white triangles form a square are drawn on a gray background.'); - * } - * - *
- * - *
- * - * function setup() { - * createCanvas(100, 100); - * - * background(200); - * - * // Start drawing the shape. - * // Draw a series of quadrilaterals. - * beginShape(QUADS); - * - * // Left rectangle. - * vertex(30, 20); - * vertex(30, 75); - * vertex(50, 75); - * vertex(50, 20); - * - * // Right rectangle. - * vertex(65, 20); - * vertex(65, 75); - * vertex(85, 75); - * vertex(85, 20); - * - * // Stop drawing the shape. - * endShape(); - * - * describe('Two white rectangles drawn on a gray background.'); - * } - * - *
- * - *
- * - * function setup() { - * createCanvas(100, 100); - * - * background(200); - * - * // Start drawing the shape. - * // Draw a series of quadrilaterals. - * beginShape(QUAD_STRIP); - * - * // Add vertices. - * vertex(30, 20); - * vertex(30, 75); - * vertex(50, 20); - * vertex(50, 75); - * vertex(65, 20); - * vertex(65, 75); - * vertex(85, 20); - * vertex(85, 75); - * - * // Stop drawing the shape. - * endShape(); - * - * describe('Three white rectangles that share edges are drawn on a gray background.'); - * } - * - *
- * - *
- * - * function setup() { - * createCanvas(100, 100, WEBGL); - * - * background(200); - * - * // Start drawing the shape. - * // Draw a series of quadrilaterals. - * beginShape(PATH); - * - * // Add the vertices. - * vertex(-30, -30, 0); - * vertex(30, -30, 0); - * vertex(30, -10, 0); - * vertex(-10, -10, 0); - * vertex(-10, 10, 0); - * vertex(30, 10, 0); - * vertex(30, 30, 0); - * vertex(-30, 30, 0); - * - * // Stop drawing the shape. - * // Connect the first and last vertices. - * endShape(CLOSE); - * - * describe('A blocky C shape drawn in white on a gray background.'); - * } - * - *
- * - *
- * - * // Click and drag with the mouse to view the scene from different angles. - * - * function setup() { - * createCanvas(100, 100, WEBGL); - * - * describe('A blocky C shape drawn in red, blue, and green on a gray background.'); - * } - * - * function draw() { - * background(200); - * - * // Enable orbiting with the mouse. - * orbitControl(); - * - * // Start drawing the shape. - * // Draw a series of quadrilaterals. - * beginShape(PATH); - * - * // Add the vertices. - * fill('red'); - * stroke('red'); - * vertex(-30, -30, 0); - * vertex(30, -30, 0); - * vertex(30, -10, 0); - * fill('green'); - * stroke('green'); - * vertex(-10, -10, 0); - * vertex(-10, 10, 0); - * vertex(30, 10, 0); - * fill('blue'); - * stroke('blue'); - * vertex(30, 30, 0); - * vertex(-30, 30, 0); - * - * // Stop drawing the shape. - * // Connect the first and last vertices. - * endShape(CLOSE); - * } - * - *
- */ - fn.beginShape = function(kind) { - // p5._validateParameters('beginShape', arguments); - this._renderer.beginShape(...arguments); - }; - - /** - * Adds a Bézier curve segment to a custom shape. - * - * `bezierVertex()` adds a curved segment to custom shapes. The Bézier curves - * it creates are defined like those made by the - * bezier() function. `bezierVertex()` must be - * called between the - * beginShape() and - * endShape() functions. The curved segment uses - * the previous vertex as the first anchor point, so there must be at least - * one call to vertex() before `bezierVertex()` can - * be used. - * - * The first four parameters, `x2`, `y2`, `x3`, and `y3`, set the curve’s two - * control points. The control points "pull" the curve towards them. - * - * The fifth and sixth parameters, `x4`, and `y4`, set the last anchor point. - * The last anchor point is where the curve ends. - * - * Bézier curves can also be drawn in 3D using WebGL mode. The 3D version of - * `bezierVertex()` has eight arguments because each point has x-, y-, and - * z-coordinates. - * - * Note: `bezierVertex()` won’t work when an argument is passed to - * beginShape(). - * - * @method bezierVertex - * @param {Number} x x-coordinate of the first control point. - * @param {Number} y y-coordinate of the first control point. - * @param {Number} [u] - * @param {Number} [v] - * - * @example - *
- * - * function setup() { - * createCanvas(100, 100); - * - * background(200); - * - * // Style the shape. - * noFill(); - * - * // Start drawing the shape. - * beginShape(); - * - * // Add the first anchor point. - * vertex(30, 20); - * - * // Add the Bézier vertex. - * bezierVertex(80, 0, 80, 75, 30, 75); - * - * // Stop drawing the shape. - * endShape(); - * - * describe('A black C curve on a gray background.'); - * } - * - *
- * - *
- * - * function setup() { - * createCanvas(100, 100); - * - * background(200); - * - * // Draw the anchor points in black. - * stroke(0); - * strokeWeight(5); - * point(30, 20); - * point(30, 75); - * - * // Draw the control points in red. - * stroke(255, 0, 0); - * point(80, 0); - * point(80, 75); - * - * // Style the shape. - * noFill(); - * stroke(0); - * strokeWeight(1); - * - * // Start drawing the shape. - * beginShape(); - * - * // Add the first anchor point. - * vertex(30, 20); - * - * // Add the Bézier vertex. - * bezierVertex(80, 0, 80, 75, 30, 75); - * - * // Stop drawing the shape. - * endShape(); - * - * // Draw red lines from the anchor points to the control points. - * stroke(255, 0, 0); - * line(30, 20, 80, 0); - * line(30, 75, 80, 75); - * - * describe( - * 'A gray square with three curves. A black curve has two straight, red lines that extend from its ends. The endpoints of all the curves are marked with dots.' - * ); - * } - * - *
- * - *
- * - * // Click the mouse near the red dot in the top-right corner - * // and drag to change the curve's shape. - * - * let x2 = 80; - * let y2 = 0; - * let isChanging = false; - * - * function setup() { - * createCanvas(100, 100); - * - * describe( - * 'A gray square with three curves. A black curve has two straight, red lines that extend from its ends. The endpoints of all the curves are marked with dots.' - * ); - * } - * - * function draw() { - * background(200); - * - * // Draw the anchor points in black. - * stroke(0); - * strokeWeight(5); - * point(30, 20); - * point(30, 75); - * - * // Draw the control points in red. - * stroke(255, 0, 0); - * point(x2, y2); - * point(80, 75); - * - * // Style the shape. - * noFill(); - * stroke(0); - * strokeWeight(1); - * - * // Start drawing the shape. - * beginShape(); - * - * // Add the first anchor point. - * vertex(30, 20); - * - * // Add the Bézier vertex. - * bezierVertex(x2, y2, 80, 75, 30, 75); - * - * // Stop drawing the shape. - * endShape(); - * - * // Draw red lines from the anchor points to the control points. - * stroke(255, 0, 0); - * line(30, 20, x2, y2); - * line(30, 75, 80, 75); - * } - * - * // Start changing the first control point if the user clicks near it. - * function mousePressed() { - * if (dist(mouseX, mouseY, x2, y2) < 20) { - * isChanging = true; - * } - * } - * - * // Stop changing the first control point when the user releases the mouse. - * function mouseReleased() { - * isChanging = false; - * } - * - * // Update the first control point while the user drags the mouse. - * function mouseDragged() { - * if (isChanging === true) { - * x2 = mouseX; - * y2 = mouseY; - * } - * } - * - *
- * - *
- * - * function setup() { - * createCanvas(100, 100); - * - * background(200); - * - * // Start drawing the shape. - * beginShape(); - * - * // Add the first anchor point. - * vertex(30, 20); - * - * // Add the Bézier vertices. - * bezierVertex(80, 0, 80, 75, 30, 75); - * bezierVertex(50, 80, 60, 25, 30, 20); - * - * // Stop drawing the shape. - * endShape(); - * - * describe('A crescent moon shape drawn in white on a gray background.'); - * } - * - *
- * - *
- * - * // Click and drag the mouse to view the scene from different angles. - * - * function setup() { - * createCanvas(100, 100, WEBGL); - * - * describe('A crescent moon shape drawn in white on a blue background. When the user drags the mouse, the scene rotates and a second moon is revealed.'); - * } - * - * function draw() { - * background('midnightblue'); - * - * // Enable orbiting with the mouse. - * orbitControl(); - * - * // Style the moons. - * noStroke(); - * fill('lemonchiffon'); - * - * // Draw the first moon. - * beginShape(); - * vertex(-20, -30, 0); - * bezierVertex(30, -50, 0, 30, 25, 0, -20, 25, 0); - * bezierVertex(0, 30, 0, 10, -25, 0, -20, -30, 0); - * endShape(); - * - * // Draw the second moon. - * beginShape(); - * vertex(-20, -30, -20); - * bezierVertex(30, -50, -20, 30, 25, -20, -20, 25, -20); - * bezierVertex(0, 30, -20, 10, -25, -20, -20, -30, -20); - * endShape(); - * } - * - *
- */ - - /** - * @method bezierVertex - * @param {Number} x - * @param {Number} y - * @param {Number} z - * @param {Number} [u] - * @param {Number} [v] - */ - fn.bezierVertex = function(...args) { - this._renderer.bezierVertex(...args); - }; - - /** - * Adds a spline curve segment to a custom shape. - * - * `splineVertex()` adds a curved segment to custom shapes. The spline curves - * it creates are defined like those made by the - * curve() function. `splineVertex()` must be called - * between the beginShape() and - * endShape() functions. - * - * Spline curves can form shapes and curves that slope gently. They’re like - * cables that are attached to a set of points. Splines are defined by two - * anchor points and two control points. `splineVertex()` must be called at - * least four times between - * beginShape() and - * endShape() in order to draw a curve: - * - * ```js - * beginShape(); - * - * // Add the first control point. - * splineVertex(84, 91); - * - * // Add the anchor points to draw between. - * splineVertex(68, 19); - * splineVertex(21, 17); - * - * // Add the second control point. - * splineVertex(32, 91); - * - * endShape(); - * ``` - * - * The code snippet above would only draw the curve between the anchor points, - * similar to the curve() function. The segments - * between the control and anchor points can be drawn by calling - * `splineVertex()` with the coordinates of the control points: - * - * ```js - * beginShape(); - * - * // Add the first control point and draw a segment to it. - * splineVertex(84, 91); - * splineVertex(84, 91); - * - * // Add the anchor points to draw between. - * splineVertex(68, 19); - * splineVertex(21, 17); - * - * // Add the second control point. - * splineVertex(32, 91); - * - * // Uncomment the next line to draw the segment to the second control point. - * // splineVertex(32, 91); - * - * endShape(); - * ``` - * - * The first two parameters, `x` and `y`, set the vertex’s location. For - * example, calling `splineVertex(10, 10)` adds a point to the curve at - * `(10, 10)`. - * - * Spline curves can also be drawn in 3D using WebGL mode. The 3D version of - * `splineVertex()` has three arguments because each point has x-, y-, and - * z-coordinates. By default, the vertex’s z-coordinate is set to 0. - * - * Note: `splineVertex()` won’t work when an argument is passed to - * beginShape(). - * - * @method curveVertex - * @param {Number} x x-coordinate of the vertex - * @param {Number} y y-coordinate of the vertex - * @chainable - * - * @example - *
- * - * function setup() { - * createCanvas(100, 100); - * - * background(200); - * - * // Style the shape. - * noFill(); - * strokeWeight(1); - * - * // Start drawing the shape. - * beginShape(); - * - * // Add the first control point. - * splineVertex(32, 91); - * - * // Add the anchor points. - * splineVertex(21, 17); - * splineVertex(68, 19); - * - * // Add the second control point. - * splineVertex(84, 91); - * - * // Stop drawing the shape. - * endShape(); - * - * // Style the anchor and control points. - * strokeWeight(5); - * - * // Draw the anchor points in black. - * stroke(0); - * point(21, 17); - * point(68, 19); - * - * // Draw the control points in red. - * stroke(255, 0, 0); - * point(32, 91); - * point(84, 91); - * - * describe( - * 'A black curve drawn on a gray background. The curve has black dots at its ends. Two red dots appear near the bottom of the canvas.' - * ); - * } - * - *
- * - *
- * - * function setup() { - * createCanvas(100, 100); - * - * background(200); - * - * // Style the shape. - * noFill(); - * strokeWeight(1); - * - * // Start drawing the shape. - * beginShape(); - * - * // Add the first control point and draw a segment to it. - * splineVertex(32, 91); - * splineVertex(32, 91); - * - * // Add the anchor points. - * splineVertex(21, 17); - * splineVertex(68, 19); - * - * // Add the second control point. - * splineVertex(84, 91); - * - * // Stop drawing the shape. - * endShape(); - * - * // Style the anchor and control points. - * strokeWeight(5); - * - * // Draw the anchor points in black. - * stroke(0); - * point(21, 17); - * point(68, 19); - * - * // Draw the control points in red. - * stroke(255, 0, 0); - * point(32, 91); - * point(84, 91); - * - * describe( - * 'A black curve drawn on a gray background. The curve passes through one red dot and two black dots. Another red dot appears near the bottom of the canvas.' - * ); - * } - * - *
- * - *
- * - * function setup() { - * createCanvas(100, 100); - * - * background(200); - * - * // Style the shape. - * noFill(); - * strokeWeight(1); - * - * // Start drawing the shape. - * beginShape(); - * - * // Add the first control point and draw a segment to it. - * splineVertex(32, 91); - * splineVertex(32, 91); - * - * // Add the anchor points. - * splineVertex(21, 17); - * splineVertex(68, 19); - * - * // Add the second control point and draw a segment to it. - * splineVertex(84, 91); - * splineVertex(84, 91); - * - * // Stop drawing the shape. - * endShape(); - * - * // Style the anchor and control points. - * strokeWeight(5); - * - * // Draw the anchor points in black. - * stroke(0); - * point(21, 17); - * point(68, 19); - * - * // Draw the control points in red. - * stroke(255, 0, 0); - * point(32, 91); - * point(84, 91); - * - * describe( - * 'A black U curve drawn upside down on a gray background. The curve passes from one red dot through two black dots and ends at another red dot.' - * ); - * } - * - *
- * - *
- * - * // Click the mouse near the red dot in the bottom-left corner - * // and drag to change the curve's shape. - * - * let x1 = 32; - * let y1 = 91; - * let isChanging = false; - * - * function setup() { - * createCanvas(100, 100); - * - * describe( - * 'A black U curve drawn upside down on a gray background. The curve passes from one red dot through two black dots and ends at another red dot.' - * ); - * } - * - * function draw() { - * background(200); - * - * // Style the shape. - * noFill(); - * stroke(0); - * strokeWeight(1); - * - * // Start drawing the shape. - * beginShape(); - * - * // Add the first control point and draw a segment to it. - * splineVertex(x1, y1); - * splineVertex(x1, y1); - * - * // Add the anchor points. - * splineVertex(21, 17); - * splineVertex(68, 19); - * - * // Add the second control point and draw a segment to it. - * splineVertex(84, 91); - * splineVertex(84, 91); - * - * // Stop drawing the shape. - * endShape(); - * - * // Style the anchor and control points. - * strokeWeight(5); - * - * // Draw the anchor points in black. - * stroke(0); - * point(21, 17); - * point(68, 19); - * - * // Draw the control points in red. - * stroke(255, 0, 0); - * point(x1, y1); - * point(84, 91); - * } - * - * // Start changing the first control point if the user clicks near it. - * function mousePressed() { - * if (dist(mouseX, mouseY, x1, y1) < 20) { - * isChanging = true; - * } - * } - * - * // Stop changing the first control point when the user releases the mouse. - * function mouseReleased() { - * isChanging = false; - * } - * - * // Update the first control point while the user drags the mouse. - * function mouseDragged() { - * if (isChanging === true) { - * x1 = mouseX; - * y1 = mouseY; - * } - * } - * - *
- * - *
- * - * function setup() { - * createCanvas(100, 100); - * - * background(200); - * - * // Start drawing the shape. - * beginShape(); - * - * // Add the first control point and draw a segment to it. - * splineVertex(32, 91); - * splineVertex(32, 91); - * - * // Add the anchor points. - * splineVertex(21, 17); - * splineVertex(68, 19); - * - * // Add the second control point. - * splineVertex(84, 91); - * splineVertex(84, 91); - * - * // Stop drawing the shape. - * endShape(); - * - * describe('A ghost shape drawn in white on a gray background.'); - * } - * - *
- */ - - /** - * @method curveVertex - * @param {Number} x - * @param {Number} y - * @param {Number} [z] z-coordinate of the vertex. - * @chainable - * - * @example - *
- * - * // Click and drag the mouse to view the scene from different angles. - * - * function setup() { - * createCanvas(100, 100, WEBGL); - * - * describe('A ghost shape drawn in white on a blue background. When the user drags the mouse, the scene rotates to reveal the outline of a second ghost.'); - * } - * - * function draw() { - * background('midnightblue'); - * - * // Enable orbiting with the mouse. - * orbitControl(); - * - * // Draw the first ghost. - * noStroke(); - * fill('ghostwhite'); - * - * beginShape(); - * splineVertex(-28, 41, 0); - * splineVertex(-28, 41, 0); - * splineVertex(-29, -33, 0); - * splineVertex(18, -31, 0); - * splineVertex(34, 41, 0); - * splineVertex(34, 41, 0); - * endShape(); - * - * // Draw the second ghost. - * noFill(); - * stroke('ghostwhite'); - * - * beginShape(); - * splineVertex(-28, 41, -20); - * splineVertex(-28, 41, -20); - * splineVertex(-29, -33, -20); - * splineVertex(18, -31, -20); - * splineVertex(34, 41, -20); - * splineVertex(34, 41, -20); - * endShape(); - * } - * - *
- */ - fn.curveVertex = function(...args) { - // p5._validateParameters('curveVertex', args); - this._renderer.splineVertex(...args); - return this; - }; - - /** - * Begins adding vertices to a custom shape. - * - * The beginShape() and `endShape()` functions - * allow for creating custom shapes in 2D or 3D. - * beginShape() begins adding vertices to a - * custom shape and `endShape()` stops adding them. - * - * The first parameter, `mode`, is optional. By default, the first and last - * vertices of a shape aren't connected. If the constant `CLOSE` is passed, as - * in `endShape(CLOSE)`, then the first and last vertices will be connected. - * - * The second parameter, `count`, is also optional. In WebGL mode, it’s more - * efficient to draw many copies of the same shape using a technique called - * instancing. - * The `count` parameter tells WebGL mode how many copies to draw. For - * example, calling `endShape(CLOSE, 400)` after drawing a custom shape will - * make it efficient to draw 400 copies. This feature requires - * writing a custom shader. - * - * After calling beginShape(), shapes can be - * built by calling vertex(), - * bezierVertex(), - * quadraticVertex(), and/or - * splineVertex(). Calling - * `endShape()` will stop adding vertices to the - * shape. Each shape will be outlined with the current stroke color and filled - * with the current fill color. - * - * Transformations such as translate(), - * rotate(), and - * scale() don't work between - * beginShape() and `endShape()`. It's also not - * possible to use other shapes, such as ellipse() or - * rect(), between - * beginShape() and `endShape()`. - * - * @method endShape - * @param {CLOSE} [mode] use CLOSE to close the shape - * @param {Integer} [count] number of times you want to draw/instance the shape (for WebGL mode). - * @chainable - * - * @example - *
- * - * function setup() { - * createCanvas(100, 100); - * - * background(200); - * - * // Style the shapes. - * noFill(); - * - * // Left triangle. - * beginShape(); - * vertex(20, 20); - * vertex(45, 20); - * vertex(45, 80); - * endShape(CLOSE); - * - * // Right triangle. - * beginShape(); - * vertex(50, 20); - * vertex(75, 20); - * vertex(75, 80); - * endShape(); - * - * describe( - * 'Two sets of black lines drawn on a gray background. The three lines on the left form a right triangle. The two lines on the right form a right angle.' - * ); - * } - * - *
- * - *
- * - * // Note: A "uniform" is a global variable within a shader program. - * - * // Create a string with the vertex shader program. - * // The vertex shader is called for each vertex. - * let vertSrc = `#version 300 es - * - * precision mediump float; - * - * in vec3 aPosition; - * flat out int instanceID; - * - * uniform mat4 uModelViewMatrix; - * uniform mat4 uProjectionMatrix; - * - * void main() { - * - * // Copy the instance ID to the fragment shader. - * instanceID = gl_InstanceID; - * vec4 positionVec4 = vec4(aPosition, 1.0); - * - * // gl_InstanceID represents a numeric value for each instance. - * // Using gl_InstanceID allows us to move each instance separately. - * // Here we move each instance horizontally by ID * 23. - * float xOffset = float(gl_InstanceID) * 23.0; - * - * // Apply the offset to the final position. - * gl_Position = uProjectionMatrix * uModelViewMatrix * (positionVec4 - - * vec4(xOffset, 0.0, 0.0, 0.0)); - * } - * `; - * - * // Create a string with the fragment shader program. - * // The fragment shader is called for each pixel. - * let fragSrc = `#version 300 es - * - * precision mediump float; - * - * out vec4 outColor; - * flat in int instanceID; - * uniform float numInstances; - * - * void main() { - * vec4 red = vec4(1.0, 0.0, 0.0, 1.0); - * vec4 blue = vec4(0.0, 0.0, 1.0, 1.0); - * - * // Normalize the instance ID. - * float normId = float(instanceID) / numInstances; - * - * // Mix between two colors using the normalized instance ID. - * outColor = mix(red, blue, normId); - * } - * `; - * - * function setup() { - * createCanvas(100, 100, WEBGL); - * - * // Create a p5.Shader object. - * let myShader = createShader(vertSrc, fragSrc); - * - * background(220); - * - * // Compile and apply the p5.Shader. - * shader(myShader); - * - * // Set the numInstances uniform. - * myShader.setUniform('numInstances', 4); - * - * // Translate the origin to help align the drawing. - * translate(25, -10); - * - * // Style the shapes. - * noStroke(); - * - * // Draw the shapes. - * beginShape(); - * vertex(0, 0); - * vertex(0, 20); - * vertex(20, 20); - * vertex(20, 0); - * vertex(0, 0); - * endShape(CLOSE, 4); - * - * describe('A row of four squares. Their colors transition from purple on the left to red on the right'); - * } - * - *
- */ - fn.endShape = function(mode, count = 1) { - // p5._validateParameters('endShape', arguments); - if (count < 1) { - console.log('🌸 p5.js says: You can not have less than one instance'); - count = 1; - } - - this._renderer.endShape(mode, count); - }; - - /** - * Sets the normal vector for vertices in a custom 3D shape. - * - * 3D shapes created with beginShape() and - * endShape() are made by connecting sets of - * points called vertices. Each vertex added with - * vertex() has a normal vector that points away - * from it. The normal vector controls how light reflects off the shape. - * - * `normal()` can be called two ways with different parameters to define the - * normal vector's components. - * - * The first way to call `normal()` has three parameters, `x`, `y`, and `z`. - * If `Number`s are passed, as in `normal(1, 2, 3)`, they set the x-, y-, and - * z-components of the normal vector. - * - * The second way to call `normal()` has one parameter, `vector`. If a - * p5.Vector object is passed, as in - * `normal(myVector)`, its components will be used to set the normal vector. - * - * `normal()` changes the normal vector of vertices added to a custom shape - * with vertex(). `normal()` must be called between - * the beginShape() and - * endShape() functions, just like - * vertex(). The normal vector set by calling - * `normal()` will affect all following vertices until `normal()` is called - * again: - * - * ```js - * beginShape(); - * - * // Set the vertex normal. - * normal(-0.4, -0.4, 0.8); - * - * // Add a vertex. - * vertex(-30, -30, 0); - * - * // Set the vertex normal. - * normal(0, 0, 1); - * - * // Add vertices. - * vertex(30, -30, 0); - * vertex(30, 30, 0); - * - * // Set the vertex normal. - * normal(0.4, -0.4, 0.8); - * - * // Add a vertex. - * vertex(-30, 30, 0); - * - * endShape(); - * ``` - * - * @method normal - * @param {p5.Vector} vector vertex normal as a p5.Vector object. - * @chainable - * - * @example - *
- * - * // Click the and drag the mouse to view the scene from a different angle. - * - * function setup() { - * createCanvas(100, 100, WEBGL); - * - * describe( - * 'A colorful square on a black background. The square changes color and rotates when the user drags the mouse. Parts of its surface reflect light in different directions.' - * ); - * } - * - * function draw() { - * background(0); - * - * // Enable orbiting with the mouse. - * orbitControl(); - * - * // Style the shape. - * normalMaterial(); - * noStroke(); - * - * // Draw the shape. - * beginShape(); - * vertex(-30, -30, 0); - * vertex(30, -30, 0); - * vertex(30, 30, 0); - * vertex(-30, 30, 0); - * endShape(); - * } - * - *
- * - *
- * - * // Click the and drag the mouse to view the scene from a different angle. - * - * function setup() { - * createCanvas(100, 100, WEBGL); - * - * describe( - * 'A colorful square on a black background. The square changes color and rotates when the user drags the mouse. Parts of its surface reflect light in different directions.' - * ); - * } - * - * function draw() { - * background(0); - * - * // Enable orbiting with the mouse. - * orbitControl(); - * - * // Style the shape. - * normalMaterial(); - * noStroke(); - * - * // Draw the shape. - * // Use normal() to set vertex normals. - * beginShape(); - * normal(-0.4, -0.4, 0.8); - * vertex(-30, -30, 0); - * - * normal(0, 0, 1); - * vertex(30, -30, 0); - * vertex(30, 30, 0); - * - * normal(0.4, -0.4, 0.8); - * vertex(-30, 30, 0); - * endShape(); - * } - * - *
- * - *
- * - * // Click the and drag the mouse to view the scene from a different angle. - * - * function setup() { - * createCanvas(100, 100, WEBGL); - * - * describe( - * 'A colorful square on a black background. The square changes color and rotates when the user drags the mouse. Parts of its surface reflect light in different directions.' - * ); - * } - * - * function draw() { - * background(0); - * - * // Enable orbiting with the mouse. - * orbitControl(); - * - * // Style the shape. - * normalMaterial(); - * noStroke(); - * - * // Create p5.Vector objects. - * let n1 = createVector(-0.4, -0.4, 0.8); - * let n2 = createVector(0, 0, 1); - * let n3 = createVector(0.4, -0.4, 0.8); - * - * // Draw the shape. - * // Use normal() to set vertex normals. - * beginShape(); - * normal(n1); - * vertex(-30, -30, 0); - * - * normal(n2); - * vertex(30, -30, 0); - * vertex(30, 30, 0); - * - * normal(n3); - * vertex(-30, 30, 0); - * endShape(); - * } - * - *
- */ - - /** - * @method normal - * @param {Number} x x-component of the vertex normal. - * @param {Number} y y-component of the vertex normal. - * @param {Number} z z-component of the vertex normal. - * @chainable - */ - fn.normal = function(x, y, z) { - this._assert3d('normal'); - // p5._validateParameters('normal', arguments); - this._renderer.normal(...arguments); - - return this; - }; - - /** - * Sets the shader's vertex property or attribute variables. - * - * A vertex property, or vertex attribute, is a variable belonging to a vertex in a shader. p5.js provides some - * default properties, such as `aPosition`, `aNormal`, `aVertexColor`, etc. These are - * set using vertex(), normal() - * and fill() respectively. Custom properties can also - * be defined within beginShape() and - * endShape(). - * - * The first parameter, `propertyName`, is a string with the property's name. - * This is the same variable name which should be declared in the shader, such as - * `in vec3 aProperty`, similar to .`setUniform()`. - * - * The second parameter, `data`, is the value assigned to the shader variable. This - * value will be applied to subsequent vertices created with - * vertex(). It can be a Number or an array of numbers, - * and in the shader program the type can be declared according to the WebGL - * specification. Common types include `float`, `vec2`, `vec3`, `vec4` or matrices. - * - * See also the vertexProperty() method on - * Geometry objects. - * - * @method vertexProperty - * @for p5 - * @param {String} attributeName the name of the vertex attribute. - * @param {Number|Number[]} data the data tied to the vertex attribute. - * - * @example - *
- * - * const vertSrc = `#version 300 es - * precision mediump float; - * uniform mat4 uModelViewMatrix; - * uniform mat4 uProjectionMatrix; - * - * in vec3 aPosition; - * in vec2 aOffset; - * - * void main(){ - * vec4 positionVec4 = vec4(aPosition.xyz, 1.0); - * positionVec4.xy += aOffset; - * gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4; - * } - * `; - * - * const fragSrc = `#version 300 es - * precision mediump float; - * out vec4 outColor; - * void main(){ - * outColor = vec4(0.0, 1.0, 1.0, 1.0); - * } - * `; - * - * function setup(){ - * createCanvas(100, 100, WEBGL); - * - * // Create and use the custom shader. - * const myShader = createShader(vertSrc, fragSrc); - * shader(myShader); - * - * describe('A wobbly, cyan circle on a gray background.'); - * } - * - * function draw(){ - * // Set the styles - * background(125); - * noStroke(); - * - * // Draw the circle. - * beginShape(); - * for (let i = 0; i < 30; i++){ - * const x = 40 * cos(i/30 * TWO_PI); - * const y = 40 * sin(i/30 * TWO_PI); - * - * // Apply some noise to the coordinates. - * const xOff = 10 * noise(x + millis()/1000) - 5; - * const yOff = 10 * noise(y + millis()/1000) - 5; - * - * // Apply these noise values to the following vertex. - * vertexProperty('aOffset', [xOff, yOff]); - * vertex(x, y); - * } - * endShape(CLOSE); - * } - * - *
- * - *
- * - * let myShader; - * const cols = 10; - * const rows = 10; - * const cellSize = 6; - * - * const vertSrc = `#version 300 es - * precision mediump float; - * uniform mat4 uProjectionMatrix; - * uniform mat4 uModelViewMatrix; - * - * in vec3 aPosition; - * in vec3 aNormal; - * in vec3 aVertexColor; - * in float aDistance; - * - * out vec3 vVertexColor; - * - * void main(){ - * vec4 positionVec4 = vec4(aPosition, 1.0); - * positionVec4.xyz += aDistance * aNormal * 2.0;; - * vVertexColor = aVertexColor; - * gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4; - * } - * `; - * - * const fragSrc = `#version 300 es - * precision mediump float; - * - * in vec3 vVertexColor; - * out vec4 outColor; - * - * void main(){ - * outColor = vec4(vVertexColor, 1.0); - * } - * `; - * - * function setup(){ - * createCanvas(100, 100, WEBGL); - * - * // Create and apply the custom shader. - * myShader = createShader(vertSrc, fragSrc); - * shader(myShader); - * noStroke(); - * describe('A blue grid, which moves away from the mouse position, on a gray background.'); - * } - * - * function draw(){ - * background(200); - * - * // Draw the grid in the middle of the screen. - * translate(-cols*cellSize/2, -rows*cellSize/2); - * beginShape(QUADS); - * for (let i = 0; i < cols; i++) { - * for (let j = 0; j < rows; j++) { - * - * // Calculate the cell position. - * let x = i * cellSize; - * let y = j * cellSize; - * - * fill(j/rows*255, j/cols*255, 255); - * - * // Calculate the distance from the corner of each cell to the mouse. - * let distance = dist(x, y, mouseX, mouseY); - * - * // Send the distance to the shader. - * vertexProperty('aDistance', min(distance, 100)); - * - * vertex(x, y); - * vertex(x + cellSize, y); - * vertex(x + cellSize, y + cellSize); - * vertex(x, y + cellSize); - * } - * } - * endShape(); - * } - * - *
- */ - fn.vertexProperty = function(attributeName, data){ - // this._assert3d('vertexProperty'); - // p5._validateParameters('vertexProperty', arguments); - this._renderer.vertexProperty(attributeName, data); - }; -} - -export default vertex; - -if(typeof p5 !== 'undefined'){ - vertex(p5, p5.prototype); -} diff --git a/test/unit/core/vertex.js b/test/unit/core/custom_shapes.js similarity index 87% rename from test/unit/core/vertex.js rename to test/unit/core/custom_shapes.js index a9b0425639..6ce6423579 100644 --- a/test/unit/core/vertex.js +++ b/test/unit/core/custom_shapes.js @@ -1,7 +1,7 @@ import p5 from '../../../src/app.js'; import { vi } from 'vitest'; -suite('Vertex', function() { +suite('Custom Shapes', function() { var myp5; let _friendlyErrorSpy; @@ -33,10 +33,10 @@ suite('Vertex', function() { }); }); - suite('p5.prototype.curveVertex', function() { + suite('p5.prototype.splineVertex', function() { test('should be a function', function() { - assert.ok(myp5.curveVertex); - assert.typeOf(myp5.curveVertex, 'function'); + assert.ok(myp5.splineVertex); + assert.typeOf(myp5.splineVertex, 'function'); }); });