p5
Version:
[](https://www.npmjs.com/package/p5)
895 lines (839 loc) • 29.5 kB
JavaScript
import { G as GRID, A as AXES } from '../constants-BRcElHU3.js';
import { Vector } from '../math/p5.Vector.js';
/**
* @module 3D
* @submodule Interaction
* @for p5
* @requires core
*/
function interaction(p5, fn){
/**
* Allows the user to orbit around a 3D sketch using a mouse, trackpad, or
* touchscreen.
*
* 3D sketches are viewed through an imaginary camera. Calling
* `orbitControl()` within the <a href="#/p5/draw">draw()</a> function allows
* the user to change the camera’s position:
*
* ```js
* function draw() {
* background(200);
*
* // Enable orbiting with the mouse.
* orbitControl();
*
* // Rest of sketch.
* }
* ```
*
* Left-clicking and dragging or swipe motion will rotate the camera position
* about the center of the sketch. Right-clicking and dragging or multi-swipe
* will pan the camera position without rotation. Using the mouse wheel
* (scrolling) or pinch in/out will move the camera further or closer from the
* center of the sketch.
*
* The first three parameters, `sensitivityX`, `sensitivityY`, and
* `sensitivityZ`, are optional. They’re numbers that set the sketch’s
* sensitivity to movement along each axis. For example, calling
* `orbitControl(1, 2, -1)` keeps movement along the x-axis at its default
* value, makes the sketch twice as sensitive to movement along the y-axis,
* and reverses motion along the z-axis. By default, all sensitivity values
* are 1.
*
* The fourth parameter, `options`, is also optional. It’s an object that
* changes the behavior of orbiting. For example, calling
* `orbitControl(1, 1, 1, options)` keeps the default sensitivity values while
* changing the behaviors set with `options`. The object can have the
* following properties:
*
* ```js
* let options = {
* // Setting this to false makes mobile interactions smoother by
* // preventing accidental interactions with the page while orbiting.
* // By default, it's true.
* disableTouchActions: true,
*
* // Setting this to true makes the camera always rotate in the
* // direction the mouse/touch is moving.
* // By default, it's false.
* freeRotation: false
* };
*
* orbitControl(1, 1, 1, options);
* ```
*
* @method orbitControl
* @for p5
* @param {Number} [sensitivityX] sensitivity to movement along the x-axis. Defaults to 1.
* @param {Number} [sensitivityY] sensitivity to movement along the y-axis. Defaults to 1.
* @param {Number} [sensitivityZ] sensitivity to movement along the z-axis. Defaults to 1.
* @param {Object} [options] object with two optional properties, `disableTouchActions`
* and `freeRotation`. Both are `Boolean`s. `disableTouchActions`
* defaults to `true` and `freeRotation` defaults to `false`.
* @chainable
*
* @example
* <div>
* <code>
* // Click and drag the mouse to view the scene from different angles.
*
* function setup() {
* createCanvas(100, 100, WEBGL);
*
* describe('A multicolor box on a gray background. The camera angle changes when the user interacts using a mouse, trackpad, or touchscreen.');
* }
*
* function draw() {
* background(200);
*
* // Enable orbiting with the mouse.
* orbitControl();
*
* // Style the box.
* normalMaterial();
*
* // Draw the box.
* box(30, 50);
* }
* </code>
* </div>
*
* <div>
* <code>
* // Click and drag the mouse to view the scene from different angles.
*
* function setup() {
* createCanvas(100, 100, WEBGL);
*
* describe('A multicolor box on a gray background. The camera angle changes when the user interacts using a mouse, trackpad, or touchscreen.');
* }
*
* function draw() {
* background(200);
*
* // Enable orbiting with the mouse.
* // Make the interactions 3X sensitive.
* orbitControl(3, 3, 3);
*
* // Style the box.
* normalMaterial();
*
* // Draw the box.
* box(30, 50);
* }
* </code>
* </div>
*
* <div>
* <code>
* // Click and drag the mouse to view the scene from different angles.
*
* function setup() {
* createCanvas(100, 100, WEBGL);
*
* describe('A multicolor box on a gray background. The camera angle changes when the user interacts using a mouse, trackpad, or touchscreen.');
* }
*
* function draw() {
* background(200);
*
* // Create an options object.
* let options = {
* disableTouchActions: false,
* freeRotation: true
* };
*
* // Enable orbiting with the mouse.
* // Prevent accidental touch actions on touchscreen devices
* // and enable free rotation.
* orbitControl(1, 1, 1, options);
*
* // Style the box.
* normalMaterial();
*
* // Draw the box.
* box(30, 50);
* }
* </code>
* </div>
*/
// implementation based on three.js 'orbitControls':
// https://github.com/mrdoob/three.js/blob/6afb8595c0bf8b2e72818e42b64e6fe22707d896/examples/jsm/controls/OrbitControls.js#L22
fn.orbitControl = function(
sensitivityX,
sensitivityY,
sensitivityZ,
options
) {
this._assert3d('orbitControl');
// p5._validateParameters('orbitControl', arguments);
const cam = this._renderer.states.curCamera;
if (typeof sensitivityX === 'undefined') {
sensitivityX = 1;
}
if (typeof sensitivityY === 'undefined') {
sensitivityY = sensitivityX;
}
if (typeof sensitivityZ === 'undefined') {
sensitivityZ = 1;
}
if (typeof options !== 'object') {
options = {};
}
// default right-mouse and mouse-wheel behaviors (context menu and scrolling,
// respectively) are disabled here to allow use of those events for panning and
// zooming. However, whether or not to disable touch actions is an option.
// disable context menu for canvas element and add 'contextMenuDisabled'
// flag to p5 instance
if (this.contextMenuDisabled !== true) {
this.canvas.oncontextmenu = () => false;
this.contextMenuDisabled = true;
}
// disable default scrolling behavior on the canvas element and add
// 'wheelDefaultDisabled' flag to p5 instance
if (this.wheelDefaultDisabled !== true) {
this.canvas.onwheel = () => false;
this.wheelDefaultDisabled = true;
}
// disable default touch behavior on the canvas element and add
// 'touchActionsDisabled' flag to p5 instance
const { disableTouchActions = true } = options;
if (this.touchActionsDisabled !== true && disableTouchActions) {
this.canvas.style['touch-action'] = 'none';
this.touchActionsDisabled = true;
}
// If option.freeRotation is true, the camera always rotates freely in the direction
// the pointer moves. default value is false (normal behavior)
const { freeRotation = false } = options;
// get moved touches.
const movedTouches = [];
this.touches.forEach(curTouch => {
this._renderer.prevTouches.forEach(prevTouch => {
if (curTouch.id === prevTouch.id) {
const movedTouch = {
x: curTouch.x,
y: curTouch.y,
px: prevTouch.x,
py: prevTouch.y
};
movedTouches.push(movedTouch);
}
});
});
this._renderer.prevTouches = this.touches;
// The idea of using damping is based on the following website. thank you.
// https://github.com/freshfork/p5.EasyCam/blob/9782964680f6a5c4c9bee825c475d9f2021d5134/p5.easycam.js#L1124
// variables for interaction
let deltaRadius = 0;
let deltaTheta = 0;
let deltaPhi = 0;
let moveDeltaX = 0;
let moveDeltaY = 0;
// constants for dampingProcess
const damping = 0.85;
const rotateAccelerationFactor = 0.6;
const moveAccelerationFactor = 0.15;
// For touches, the appropriate scale is different
// because the distance difference is multiplied.
const mouseZoomScaleFactor = 0.01;
const touchZoomScaleFactor = 0.0004;
const scaleFactor = this.height < this.width ? this.height : this.width;
// Flag whether the mouse or touch pointer is inside the canvas
let pointersInCanvas = false;
// calculate and determine flags and variables.
if (movedTouches.length > 0) {
/* for touch */
// if length === 1, rotate
// if length > 1, zoom and move
// for touch, it is calculated based on one moved touch pointer position.
pointersInCanvas =
movedTouches[0].x > 0 && movedTouches[0].x < this.width &&
movedTouches[0].y > 0 && movedTouches[0].y < this.height;
if (movedTouches.length === 1) {
const t = movedTouches[0];
deltaTheta = -sensitivityX * (t.x - t.px) / scaleFactor;
deltaPhi = sensitivityY * (t.y - t.py) / scaleFactor;
} else {
const t0 = movedTouches[0];
const t1 = movedTouches[1];
const distWithTouches = Math.hypot(t0.x - t1.x, t0.y - t1.y);
const prevDistWithTouches = Math.hypot(t0.px - t1.px, t0.py - t1.py);
const changeDist = distWithTouches - prevDistWithTouches;
// move the camera farther when the distance between the two touch points
// decreases, move the camera closer when it increases.
deltaRadius = -changeDist * sensitivityZ * touchZoomScaleFactor;
// Move the center of the camera along with the movement of
// the center of gravity of the two touch points.
moveDeltaX = 0.5 * (t0.x + t1.x) - 0.5 * (t0.px + t1.px);
moveDeltaY = 0.5 * (t0.y + t1.y) - 0.5 * (t0.py + t1.py);
}
if (this.touches.length > 0) {
if (pointersInCanvas) {
// Initiate an interaction if touched in the canvas
this._renderer.executeRotateAndMove = true;
this._renderer.executeZoom = true;
}
} else {
// End an interaction when the touch is released
this._renderer.executeRotateAndMove = false;
this._renderer.executeZoom = false;
}
} else {
/* for mouse */
// if wheelDeltaY !== 0, zoom
// if mouseLeftButton is down, rotate
// if mouseRightButton is down, move
// For mouse, it is calculated based on the mouse position.
pointersInCanvas =
(this.mouseX > 0 && this.mouseX < this.width) &&
(this.mouseY > 0 && this.mouseY < this.height);
if (this._mouseWheelDeltaY !== 0) {
// zoom the camera depending on the value of _mouseWheelDeltaY.
// move away if positive, move closer if negative
deltaRadius = Math.sign(this._mouseWheelDeltaY) * sensitivityZ;
deltaRadius *= mouseZoomScaleFactor;
this._mouseWheelDeltaY = 0;
// start zoom when the mouse is wheeled within the canvas.
if (pointersInCanvas) this._renderer.executeZoom = true;
} else {
// quit zoom when you stop wheeling.
this._renderer.executeZoom = false;
}
if (this.mouseIsPressed) {
if (this.mouseButton.left) {
deltaTheta = -sensitivityX * this.movedX / scaleFactor;
deltaPhi = sensitivityY * this.movedY / scaleFactor;
} else if (this.mouseButton.right) {
moveDeltaX = this.movedX;
moveDeltaY = this.movedY * cam.yScale;
}
// start rotate and move when mouse is pressed within the canvas.
if (pointersInCanvas) this._renderer.executeRotateAndMove = true;
} else {
// quit rotate and move if mouse is released.
this._renderer.executeRotateAndMove = false;
}
}
// interactions
// zoom process
if (deltaRadius !== 0 && this._renderer.executeZoom) {
// accelerate zoom velocity
this._renderer.zoomVelocity += deltaRadius;
}
if (Math.abs(this._renderer.zoomVelocity) > 0.001) {
// if freeRotation is true, we use _orbitFree() instead of _orbit()
if (freeRotation) {
cam._orbitFree(
0, 0, this._renderer.zoomVelocity
);
} else {
cam._orbit(
0, 0, this._renderer.zoomVelocity
);
}
// In orthogonal projection, the scale does not change even if
// the distance to the gaze point is changed, so the projection matrix
// needs to be modified.
if (cam.projMatrix.mat4[15] !== 0) {
cam.projMatrix.mat4[0] *= Math.pow(
10, -this._renderer.zoomVelocity
);
cam.projMatrix.mat4[5] *= Math.pow(
10, -this._renderer.zoomVelocity
);
// modify uPMatrix
this._renderer.states.setValue('uPMatrix', this._renderer.states.uPMatrix.clone());
this._renderer.states.uPMatrix.mat4[0] = cam.projMatrix.mat4[0];
this._renderer.states.uPMatrix.mat4[5] = cam.projMatrix.mat4[5];
}
// damping
this._renderer.zoomVelocity *= damping;
} else {
this._renderer.zoomVelocity = 0;
}
// rotate process
if ((deltaTheta !== 0 || deltaPhi !== 0) &&
this._renderer.executeRotateAndMove) {
// accelerate rotate velocity
this._renderer.rotateVelocity.add(
deltaTheta * rotateAccelerationFactor,
deltaPhi * rotateAccelerationFactor
);
}
if (this._renderer.rotateVelocity.magSq() > 0.000001) {
// if freeRotation is true, the camera always rotates freely in the direction the pointer moves
if (freeRotation) {
cam._orbitFree(
-this._renderer.rotateVelocity.x,
this._renderer.rotateVelocity.y,
0
);
} else {
cam._orbit(
this._renderer.rotateVelocity.x,
this._renderer.rotateVelocity.y,
0
);
}
// damping
this._renderer.rotateVelocity.mult(damping);
} else {
this._renderer.rotateVelocity.set(0, 0);
}
// move process
if ((moveDeltaX !== 0 || moveDeltaY !== 0) &&
this._renderer.executeRotateAndMove) {
// Normalize movement distance
const ndcX = moveDeltaX * 2/this.width;
const ndcY = -moveDeltaY * 2/this.height;
// accelerate move velocity
this._renderer.moveVelocity.add(
ndcX * moveAccelerationFactor,
ndcY * moveAccelerationFactor
);
}
if (this._renderer.moveVelocity.magSq() > 0.000001) {
// Translate the camera so that the entire object moves
// perpendicular to the line of sight when the mouse is moved
// or when the centers of gravity of the two touch pointers move.
const local = cam._getLocalAxes();
// Calculate the z coordinate in the view coordinates of
// the center, that is, the distance to the view point
const diffX = cam.eyeX - cam.centerX;
const diffY = cam.eyeY - cam.centerY;
const diffZ = cam.eyeZ - cam.centerZ;
const viewZ = Math.sqrt(diffX * diffX + diffY * diffY + diffZ * diffZ);
// position vector of the center.
let cv = new Vector(cam.centerX, cam.centerY, cam.centerZ);
// Calculate the normalized device coordinates of the center.
cv = cam.cameraMatrix.multiplyPoint(cv);
cv = this._renderer.states.uPMatrix.multiplyAndNormalizePoint(cv);
// Move the center by this distance
// in the normalized device coordinate system.
cv.x -= this._renderer.moveVelocity.x;
cv.y -= this._renderer.moveVelocity.y;
// Calculate the translation vector
// in the direction perpendicular to the line of sight of center.
let dx, dy;
const uP = this._renderer.states.uPMatrix.mat4;
if (uP[15] === 0) {
dx = ((uP[8] + cv.x)/uP[0]) * viewZ;
dy = ((uP[9] + cv.y)/uP[5]) * viewZ;
} else {
dx = (cv.x - uP[12])/uP[0];
dy = (cv.y - uP[13])/uP[5];
}
// translate the camera.
cam.setPosition(
cam.eyeX + dx * local.x[0] + dy * local.y[0],
cam.eyeY + dx * local.x[1] + dy * local.y[1],
cam.eyeZ + dx * local.x[2] + dy * local.y[2]
);
// damping
this._renderer.moveVelocity.mult(damping);
} else {
this._renderer.moveVelocity.set(0, 0);
}
return this;
};
/**
* Adds a grid and an axes icon to clarify orientation in 3D sketches.
*
* `debugMode()` adds a grid that shows where the “ground” is in a sketch. By
* default, the grid will run through the origin `(0, 0, 0)` of the sketch
* along the XZ plane. `debugMode()` also adds an axes icon that points along
* the positive x-, y-, and z-axes. Calling `debugMode()` displays the grid
* and axes icon with their default size and position.
*
* There are four ways to call `debugMode()` with optional parameters to
* customize the debugging environment.
*
* The first way to call `debugMode()` has one parameter, `mode`. If the
* system constant `GRID` is passed, as in `debugMode(GRID)`, then the grid
* will be displayed and the axes icon will be hidden. If the constant `AXES`
* is passed, as in `debugMode(AXES)`, then the axes icon will be displayed
* and the grid will be hidden.
*
* The second way to call `debugMode()` has six parameters. The first
* parameter, `mode`, selects either `GRID` or `AXES` to be displayed. The
* next five parameters, `gridSize`, `gridDivisions`, `xOff`, `yOff`, and
* `zOff` are optional. They’re numbers that set the appearance of the grid
* (`gridSize` and `gridDivisions`) and the placement of the axes icon
* (`xOff`, `yOff`, and `zOff`). For example, calling
* `debugMode(20, 5, 10, 10, 10)` sets the `gridSize` to 20 pixels, the number
* of `gridDivisions` to 5, and offsets the axes icon by 10 pixels along the
* x-, y-, and z-axes.
*
* The third way to call `debugMode()` has five parameters. The first
* parameter, `mode`, selects either `GRID` or `AXES` to be displayed. The
* next four parameters, `axesSize`, `xOff`, `yOff`, and `zOff` are optional.
* They’re numbers that set the appearance of the size of the axes icon
* (`axesSize`) and its placement (`xOff`, `yOff`, and `zOff`).
*
* The fourth way to call `debugMode()` has nine optional parameters. The
* first five parameters, `gridSize`, `gridDivisions`, `gridXOff`, `gridYOff`,
* and `gridZOff` are numbers that set the appearance of the grid. For
* example, calling `debugMode(100, 5, 0, 0, 0)` sets the `gridSize` to 100,
* the number of `gridDivisions` to 5, and sets all the offsets to 0 so that
* the grid is centered at the origin. The next four parameters, `axesSize`,
* `xOff`, `yOff`, and `zOff` are numbers that set the appearance of the size
* of the axes icon (`axesSize`) and its placement (`axesXOff`, `axesYOff`,
* and `axesZOff`). For example, calling
* `debugMode(100, 5, 0, 0, 0, 50, 10, 10, 10)` sets the `gridSize` to 100,
* the number of `gridDivisions` to 5, and sets all the offsets to 0 so that
* the grid is centered at the origin. It then sets the `axesSize` to 50 and
* offsets the icon 10 pixels along each axis.
*
* @method debugMode
*
* @example
* <div>
* <code>
* // Click and drag the mouse to view the scene from different angles.
*
* function setup() {
* createCanvas(100, 100, WEBGL);
*
* // Enable debug mode.
* debugMode();
*
* describe('A multicolor box on a gray background. A grid and axes icon are displayed near the box.');
* }
*
* function draw() {
* background(200);
*
* // Enable orbiting with the mouse.
* orbitControl();
*
* // Style the box.
* normalMaterial();
*
* // Draw the box.
* box(20, 40);
* }
* </code>
* </div>
*
* <div>
* <code>
* // Click and drag the mouse to view the scene from different angles.
*
* function setup() {
* createCanvas(100, 100, WEBGL);
*
* // Enable debug mode.
* // Only display the axes icon.
* debugMode(AXES);
*
* describe('A multicolor box on a gray background. A grid and axes icon are displayed near the box.');
* }
*
* function draw() {
* background(200);
*
* // Enable orbiting with the mouse.
* orbitControl();
*
* // Style the box.
* normalMaterial();
*
* // Draw the box.
* box(20, 40);
* }
* </code>
* </div>
*
* <div>
* <code>
* // Click and drag the mouse to view the scene from different angles.
*
* function setup() {
* createCanvas(100, 100, WEBGL);
*
* // Enable debug mode.
* // Only display the grid and customize it:
* // - size: 50
* // - divisions: 10
* // - offsets: 0, 20, 0
* debugMode(GRID, 50, 10, 0, 20, 0);
*
* describe('A multicolor box on a gray background. A grid is displayed below the box.');
* }
*
* function draw() {
* background(200);
*
* // Enable orbiting with the mouse.
* orbitControl();
*
* // Style the box.
* normalMaterial();
*
* // Draw the box.
* box(20, 40);
* }
* </code>
* </div>
*
* <div>
* <code>
* // Click and drag the mouse to view the scene from different angles.
*
* function setup() {
* createCanvas(100, 100, WEBGL);
*
* // Enable debug mode.
* // Display the grid and axes icon and customize them:
* // Grid
* // ----
* // - size: 50
* // - divisions: 10
* // - offsets: 0, 20, 0
* // Axes
* // ----
* // - size: 50
* // - offsets: 0, 0, 0
* debugMode(50, 10, 0, 20, 0, 50, 0, 0, 0);
*
* describe('A multicolor box on a gray background. A grid is displayed below the box. An axes icon is displayed at the center of the box.');
* }
*
* function draw() {
* background(200);
*
* // Enable orbiting with the mouse.
* orbitControl();
*
* // Style the box.
* normalMaterial();
*
* // Draw the box.
* box(20, 40);
* }
* </code>
* </div>
*/
/**
* @method debugMode
* @param {(GRID|AXES)} mode either GRID or AXES
*/
/**
* @method debugMode
* @param {(GRID|AXES)} mode
* @param {Number} [gridSize] side length of the grid.
* @param {Number} [gridDivisions] number of divisions in the grid.
* @param {Number} [xOff] offset from origin along the x-axis.
* @param {Number} [yOff] offset from origin along the y-axis.
* @param {Number} [zOff] offset from origin along the z-axis.
*/
/**
* @method debugMode
* @param {(GRID|AXES)} mode
* @param {Number} [axesSize] length of axes icon markers.
* @param {Number} [xOff]
* @param {Number} [yOff]
* @param {Number} [zOff]
*/
/**
* @method debugMode
* @param {Number} [gridSize]
* @param {Number} [gridDivisions]
* @param {Number} [gridXOff] grid offset from the origin along the x-axis.
* @param {Number} [gridYOff] grid offset from the origin along the y-axis.
* @param {Number} [gridZOff] grid offset from the origin along the z-axis.
* @param {Number} [axesSize]
* @param {Number} [axesXOff] axes icon offset from the origin along the x-axis.
* @param {Number} [axesYOff] axes icon offset from the origin along the y-axis.
* @param {Number} [axesZOff] axes icon offset from the origin along the z-axis.
*/
fn.debugMode = function(...args) {
this._assert3d('debugMode');
// p5._validateParameters('debugMode', args);
// start by removing existing 'post' registered debug methods
for (let i = p5.lifecycleHooks.postdraw.length - 1; i >= 0; i--) {
// test for equality...
if (
p5.lifecycleHooks.postdraw[i].toString() === this._grid().toString() ||
p5.lifecycleHooks.postdraw[i].toString() === this._axesIcon().toString()
) {
p5.lifecycleHooks.postdraw.splice(i, 1);
}
}
// then add new debugMode functions according to the argument list
if (args[0] === GRID) {
p5.lifecycleHooks.postdraw.push(
this._grid(args[1], args[2], args[3], args[4], args[5])
);
} else if (args[0] === AXES) {
p5.lifecycleHooks.postdraw.push(
this._axesIcon(args[1], args[2], args[3], args[4])
);
} else {
p5.lifecycleHooks.postdraw.push(
this._grid(args[0], args[1], args[2], args[3], args[4])
);
p5.lifecycleHooks.postdraw.push(
this._axesIcon(args[5], args[6], args[7], args[8])
);
}
};
/**
* Turns off <a href="#/p5/debugMode">debugMode()</a> in a 3D sketch.
*
* @method noDebugMode
*
* @example
* <div>
* <code>
* // Click and drag the mouse to view the scene from different angles.
*
* function setup() {
* createCanvas(100, 100, WEBGL);
*
* // Enable debug mode.
* debugMode();
*
* describe('A multicolor box on a gray background. A grid and axes icon are displayed near the box. They disappear when the user double-clicks.');
* }
*
* function draw() {
* background(200);
*
* // Enable orbiting with the mouse.
* orbitControl();
*
* // Style the box.
* normalMaterial();
*
* // Draw the box. box(20, 40);
* }
*
* // Disable debug mode when the user double-clicks.
* function doubleClicked() {
* noDebugMode();
* }
* </code>
* </div>
*/
fn.noDebugMode = function() {
this._assert3d('noDebugMode');
// start by removing existing 'post' registered debug methods
for (let i = p5.lifecycleHooks.postdraw.length - 1; i >= 0; i--) {
// test for equality...
if (
p5.lifecycleHooks.postdraw[i].toString() === this._grid().toString() ||
p5.lifecycleHooks.postdraw[i].toString() === this._axesIcon().toString()
) {
p5.lifecycleHooks.postdraw.splice(i, 1);
}
}
};
/**
* For use with debugMode
* @private
* @method _grid
* @param {Number} [size] size of grid sides
* @param {Number} [div] number of grid divisions
* @param {Number} [xOff] offset of grid center from origin in X axis
* @param {Number} [yOff] offset of grid center from origin in Y axis
* @param {Number} [zOff] offset of grid center from origin in Z axis
*/
fn._grid = function(size, numDivs, xOff, yOff, zOff) {
if (typeof size === 'undefined') {
size = this.width / 2;
}
if (typeof numDivs === 'undefined') {
// ensure at least 2 divisions
numDivs = Math.round(size / 30) < 4 ? 4 : Math.round(size / 30);
}
if (typeof xOff === 'undefined') {
xOff = 0;
}
if (typeof yOff === 'undefined') {
yOff = 0;
}
if (typeof zOff === 'undefined') {
zOff = 0;
}
const spacing = size / numDivs;
const halfSize = size / 2;
return function() {
this.push();
this.stroke(
this._renderer.states.curStrokeColor[0] * 255,
this._renderer.states.curStrokeColor[1] * 255,
this._renderer.states.curStrokeColor[2] * 255
);
this._renderer.states.setValue('uModelMatrix', this._renderer.states.uModelMatrix.clone());
this._renderer.states.uModelMatrix.reset();
// Lines along X axis
for (let q = 0; q <= numDivs; q++) {
this.beginShape(this.LINES);
this.vertex(-halfSize + xOff, yOff, q * spacing - halfSize + zOff);
this.vertex(+halfSize + xOff, yOff, q * spacing - halfSize + zOff);
this.endShape();
}
// Lines along Z axis
for (let i = 0; i <= numDivs; i++) {
this.beginShape(this.LINES);
this.vertex(i * spacing - halfSize + xOff, yOff, -halfSize + zOff);
this.vertex(i * spacing - halfSize + xOff, yOff, +halfSize + zOff);
this.endShape();
}
this.pop();
};
};
/**
* For use with debugMode
* @private
* @method _axesIcon
* @param {Number} [size] size of axes icon lines
* @param {Number} [xOff] offset of icon from origin in X axis
* @param {Number} [yOff] offset of icon from origin in Y axis
* @param {Number} [zOff] offset of icon from origin in Z axis
*/
fn._axesIcon = function(size, xOff, yOff, zOff) {
if (typeof size === 'undefined') {
size = this.width / 20 > 40 ? this.width / 20 : 40;
}
if (typeof xOff === 'undefined') {
xOff = -this.width / 4;
}
if (typeof yOff === 'undefined') {
yOff = xOff;
}
if (typeof zOff === 'undefined') {
zOff = xOff;
}
return () => {
this.push();
this._renderer.states.setValue('uModelMatrix', this._renderer.states.uModelMatrix.clone());
this._renderer.states.uModelMatrix.reset();
// X axis
this.strokeWeight(2);
this.stroke(255, 0, 0);
this.beginShape(this.LINES);
this.vertex(xOff, yOff, zOff);
this.vertex(xOff + size, yOff, zOff);
this.endShape();
// Y axis
this.stroke(0, 255, 0);
this.beginShape(this.LINES);
this.vertex(xOff, yOff, zOff);
this.vertex(xOff, yOff + size, zOff);
this.endShape();
// Z axis
this.stroke(0, 0, 255);
this.beginShape(this.LINES);
this.vertex(xOff, yOff, zOff);
this.vertex(xOff, yOff, zOff + size);
this.endShape();
this.pop();
};
};
}
if(typeof p5 !== 'undefined'){
interaction(p5, p5.prototype);
}
export { interaction as default };