diff --git a/Insperation/Screenshot 2023-04-11 163356.png b/Insperation/Screenshot 2023-04-11 163356.png new file mode 100644 index 0000000..3dc8429 Binary files /dev/null and b/Insperation/Screenshot 2023-04-11 163356.png differ diff --git a/Insperation/Screenshot 2023-04-14 225712.png b/Insperation/Screenshot 2023-04-14 225712.png new file mode 100644 index 0000000..b856a8e Binary files /dev/null and b/Insperation/Screenshot 2023-04-14 225712.png differ diff --git a/docs/index.html b/docs/index.html index c5306aa..5da07a5 100644 --- a/docs/index.html +++ b/docs/index.html @@ -34,8 +34,8 @@ Press "P" to show/hide the control panel


-

Degrees Per Second

- +

Speed

+

Controls

diff --git a/docs/js/helper.js b/docs/js/helper.js index ca19152..5d76915 100644 --- a/docs/js/helper.js +++ b/docs/js/helper.js @@ -3,15 +3,11 @@ async function fetchConfig(className) { const config = { PolyTwistColourWidth: [ { type: "range", min: 3, max: 10, defaultValue: 5, property: "sides" }, - { type: "range", min: 1, max: 600, defaultValue: 400, property: "width" }, + { type: "range", min: 400, max: 400, defaultValue: 400, property: "width" }, + { type: "range", min: 2, max: 5, defaultValue: 5, property: "line_width" }, { type: "range", min: 1, max: 100, defaultValue: 50, property: "depth" }, - { - type: "range", - min: -180, - max: 180, - defaultValue: -90, - property: "rotation", - }, + { type: "range", min: -180, max: 180, defaultValue: -90, property: "rotation", }, + { type: "range", min: 1, max: 500, defaultValue: 100, property: "speedMultiplier", }, { type: "color", defaultValue: "#4287f5", property: "colour1" }, { type: "color", defaultValue: "#42f57b", property: "colour2" }, ], @@ -219,7 +215,7 @@ function drawEyelidAccident(x1, y1) { ctx.stroke(); } -function DrawPolygon(sides, width, rotation, colour) { +function DrawPolygon(sides, width, rotation, colour,line_width) { ctx.beginPath(); ctx.moveTo( centerX + width * Math.cos((rotation * Math.PI) / 180), @@ -229,14 +225,14 @@ function DrawPolygon(sides, width, rotation, colour) { for (var i = 1; i <= sides; i += 1) { ctx.lineTo( centerX + - width * - Math.cos((i * 2 * Math.PI) / sides + (rotation * Math.PI) / 180), + width * + Math.cos((i * 2 * Math.PI) / sides + (rotation * Math.PI) / 180), centerY + - width * Math.sin((i * 2 * Math.PI) / sides + (rotation * Math.PI) / 180) + width * Math.sin((i * 2 * Math.PI) / sides + (rotation * Math.PI) / 180) ); } ctx.strokeStyle = colour; - ctx.lineWidth = 3; + ctx.lineWidth = line_width; ctx.stroke(); } diff --git a/docs/js/index.js b/docs/js/index.js index cb14579..7ac08b6 100644 --- a/docs/js/index.js +++ b/docs/js/index.js @@ -7,7 +7,7 @@ centerX = ctx.canvas.width / 2; centerY = ctx.canvas.height / 2; -let deg_per_sec = 5; +let deg_per_sec = 10; let targetFps = 60; let frameDuration = 1000 / targetFps; @@ -39,6 +39,8 @@ function createInstance(className, args) { } } + + async function updateDrawObj() { const shapeSelector = document.getElementById("shape-selector"); const selectedShape = shapeSelector.value; @@ -52,6 +54,9 @@ async function updateDrawObj() { .map((item) => item.defaultValue); drawObj = createInstance(selectedShape, defaultValues); + + // drawObj = await createShapeWithRandomProperties(813311281, config1); + console.log(drawObj) drawObj.initialise(config); } diff --git a/docs/js/objects.js b/docs/js/objects.js index e070318..ae05084 100644 --- a/docs/js/objects.js +++ b/docs/js/objects.js @@ -1,6 +1,7 @@ class BaseShape { constructor() { this.controls = []; // Keep track of created elements and event listeners + this.speedMultiplier = 100; } initialise(config) { @@ -8,6 +9,9 @@ class BaseShape { const { element, listener } = addControl(item, this); this.controls.push({ element, listener }); } + + const { element, listener } = addControl({ type: "range", min: 1, max: 500, defaultValue: 100, property: "speedMultiplier", }, this); + this.controls.push({ element, listener }); } remove() { @@ -30,20 +34,23 @@ class BaseShape { } class PolyTwistColourWidth extends BaseShape { - constructor(sides, width, depth, rotation, colour1, colour2) { + constructor(sides, width,line_width, depth, rotation, speedMultiplier,colour1, colour2) { super(); this.sides = sides; this.width = width; + this.line_width = line_width; this.depth = depth; this.rotation = rotation; + this.speedMultiplier = speedMultiplier; this.colour1 = colour1; this.colour2 = colour2; } - draw(innerRotation) { + draw(rotation) { + rotation*=(this.speedMultiplier/100) let out_angle = 0; const innerAngle = 180 - ((this.sides - 2) * 180) / this.sides; - const scopeAngle = innerRotation - (innerAngle * Math.floor(innerRotation / innerAngle)); + const scopeAngle = rotation - (innerAngle * Math.floor(rotation / innerAngle)); if (scopeAngle < innerAngle / 2) { out_angle = innerAngle / (2 * Math.cos((2 * Math.PI * scopeAngle) / (3 * innerAngle))) - innerAngle / 2; @@ -57,7 +64,7 @@ class PolyTwistColourWidth extends BaseShape { for (let i = 0; i < this.depth; i++) { const fraction = i / this.depth; const ncolour = LerpHex(this.colour1, this.colour2, fraction); - DrawPolygon(this.sides, this.width * widthMultiplier ** i, out_angle * i + this.rotation, ncolour); + DrawPolygon(this.sides, this.width * widthMultiplier ** i, out_angle * i + this.rotation, ncolour,this.line_width); } } } @@ -68,19 +75,22 @@ class FloralPhyllo extends BaseShape { this.depth = depth; this.colour1 = colour1; this.colour2 = colour2; + this.speedMultiplier = 500; } - draw(angle) { + draw(rotation) { + rotation*=(this.speedMultiplier/100) // var c = 24; //something to do with width. but not width var c = 1; //something to do with width. but not width //dont make larger than 270 unless altering the number of colours in lerpedColours for (let n = 200; n > 0; n -= 1) { - const a = n * angle / 1000; //137.5; + // let ncolour = LerpHex(this.colour1, this.colour2, n); + const a = n * rotation / 1000; //137.5; const r = c * Math.sqrt(n); const x = r * Math.cos(a) + centerX; const y = r * Math.sin(a) + centerY; - drawEyelid(n * 2.4 + 40, x, y, this.colour1); + drawEyelid(n * 2.4 + 40, x, y, ncolour); } } } @@ -93,6 +103,7 @@ class Spiral1 extends BaseShape { } draw(rotation) { + rotation*=(this.speedMultiplier/100) var rot = Math.round((this.sides - 2) * 180 / this.sides * 2) var piv = 360 / this.sides; var stt = 0.5 * Math.PI - rad(rot) //+ rad(rotation); @@ -129,6 +140,7 @@ class FloralAccident extends BaseShape { } draw(rotation) { + rotation*=(this.speedMultiplier/100) var rot = Math.round((this.sides - 2) * 180 / this.sides * 2) var piv = 360 / this.sides; var stt = 0.5 * Math.PI - rad(rot) //+ rad(rotation); @@ -164,13 +176,13 @@ class FloralPhyllo_Accident extends BaseShape { this.colour2 = colour2; } - draw(angle) { - + draw(rotation) { + rotation*=(this.speedMultiplier/100) var c = 24; //something to do with width. but not width for (let n = 0; n < 300; n += 1) { let ncolour = LerpHex(this.colour1, this.colour2, Math.cos(rad(n / 2))); - let a = n * (angle / 1000 + 100); //137.5; + let a = n * (rotation / 1000 + 100); //137.5; let r = c * Math.sqrt(n); let x = r * Math.cos(a) + centerX; let y = r * Math.sin(a) + centerY; @@ -191,9 +203,10 @@ class Nodal_expanding extends BaseShape { this.colour_change = colour_change } - draw(step) { - let colour_change = this.colour_change / 10 - var angle = 360 / this.points * step + draw(rotation) { + rotation*=(this.speedMultiplier/100) + let colour_change = this.colour_change / 8 + var angle = 360 / this.points * rotation var start_angle = angle; var done = false; @@ -209,6 +222,7 @@ class Nodal_expanding extends BaseShape { length += this.expand; ctx.lineWidth = this.line_width;//try 1 ctx.strokeStyle = ncolour; + ctx.lineCap = "round" // ctx.strokeStyle = colourToText(ncolour); console.log(ncolour) ctx.stroke(); @@ -227,14 +241,15 @@ class Nodal extends BaseShape { this.colour = colour; } // Draw_nodal(300, 100, 31, rotation, "blue"); - draw(rotate) { + draw(rotation) { + rotation*=(this.speedMultiplier/100) // console.log(rotate) var angle = 360 / this.points * this.step ctx.beginPath(); var start_angle = angle; var done = false; var total_moves = 1; - ctx.moveTo(centerX + (Math.cos(rad(angle + rotate)) * this.width), centerY + (Math.sin(rad(angle + rotate)) * this.width)); + ctx.moveTo(centerX + (Math.cos(rad(angle + rotation)) * this.width), centerY + (Math.sin(rad(angle + rotation)) * this.width)); while (done != true) { if ((total_moves * this.step) % this.points != 0) { @@ -246,7 +261,7 @@ class Nodal extends BaseShape { } } for (let z = 1; z <= total_moves; z++) { - ctx.lineTo(centerX + (Math.cos(rad(angle * z + rotate)) * this.width), centerY + (Math.sin(rad(angle * z + rotate)) * this.width)); + ctx.lineTo(centerX + (Math.cos(rad(angle * z + rotation)) * this.width), centerY + (Math.sin(rad(angle * z + rotation)) * this.width)); } ctx.lineWidth = this.line_width;//try 1 ctx.strokeStyle = this.colour; @@ -263,12 +278,12 @@ class Phyllotaxis extends BaseShape { this.colour2 = colour2; } // Draw_nodal(300, 100, 31, rotation, "blue"); - draw(angle) { - + draw(rotation) { + rotation*=(this.speedMultiplier/100) for (let n = 0; n < this.nMax; n += 1) { const ncolour = LerpHex(this.colour1, this.colour2, n / this.nMax); // const ncolour = LerpHex(this.colour1, this.colour2, (n/this.nMax)**2); - const a = n * (angle / 1000)//137.5; + const a = n * (rotation / 1000)//137.5; const r = this.width * Math.sqrt(n); const x = r * Math.cos(a) + centerX; const y = r * Math.sin(a) + centerY; @@ -302,12 +317,13 @@ class SquareTwist_angle extends BaseShape { ctx.restore(); } // DrawSquareTwist_angle(400,0,rotation,"red") - draw(innerRotation) { - let out_angle = innerRotation; + draw(rotation) { + rotation*=(this.speedMultiplier/100) + let out_angle = rotation; let widthMultiplier = 1 / (2 * Math.sin(Math.PI / 180 * (130 - out_angle + 90 * Math.floor(out_angle / 90)))) + 0.5 for (let i = 0; i < 25; i++) { - this.drawSquare(innerRotation * i, this.width * widthMultiplier ** i, this.colour1) + this.drawSquare(rotation * i, this.width * widthMultiplier ** i, this.colour1) } } @@ -333,6 +349,7 @@ class rectangle_pattern1 extends BaseShape { } // Draw_rectangle_pattern1(rotation, squares, 200, "blue"); draw(rotation) { + rotation*=(this.speedMultiplier/100) for (let z = 0; z < 360; z += 360 / this.squares) { this.drawSquare(z + rotation, this.width, this.colour1); } @@ -354,14 +371,15 @@ class EyePrototype extends BaseShape { ]; this.cooldown = 0; } - drawEyelid(step) { + drawEyelid(rotation) { + rotation*=(this.speedMultiplier/100) ctx.lineWidth = 1; ctx.beginPath(); ctx.moveTo(this.points[0][0], this.points[0][1]); - ctx.quadraticCurveTo(250, 250 - step, this.points[1][0], this.points[0][1]); + ctx.quadraticCurveTo(250, 250 - rotation, this.points[1][0], this.points[0][1]); ctx.moveTo(this.points[0][0], this.points[0][1]); - ctx.quadraticCurveTo(250, 250 + step, this.points[1][0], this.points[0][1]); + ctx.quadraticCurveTo(250, 250 + rotation, this.points[1][0], this.points[0][1]); ctx.stroke(); } eyelidCut(step) { diff --git a/rfid/config.json b/rfid/config.json new file mode 100644 index 0000000..bfed6e4 --- /dev/null +++ b/rfid/config.json @@ -0,0 +1,16 @@ +{ + "PolyTwistColourWidth": [ + { "type": "range", "min": 3, "max": 10, "defaultValue": 5, "property": "sides" }, + { "type": "range", "min": 1, "max": 600, "defaultValue": 300, "property": "width" }, + { "type": "range", "min": 1, "max": 100, "defaultValue": 50, "property": "depth" }, + { "type": "range", "min": 0, "max": 360, "defaultValue": 180, "property": "rotation" }, + { "type": "color", "defaultValue": "#4287f5", "property": "colour1" }, + { "type": "color", "defaultValue": "#42f57b", "property": "colour2" } + ], + "FloralPhyllo": [ + { "type": "range", "min": 1, "max": 600, "defaultValue": 300, "property": "width" }, + { "type": "range", "min": 1, "max": 100, "defaultValue": 50, "property": "depth" }, + { "type": "color", "defaultValue": "#4287f5", "property": "colour1" }, + { "type": "color", "defaultValue": "#4287f5", "property": "colour2" } + ] + } \ No newline at end of file diff --git a/rfid/css/styles.css b/rfid/css/styles.css new file mode 100644 index 0000000..612d6e4 --- /dev/null +++ b/rfid/css/styles.css @@ -0,0 +1,111 @@ +body { + -webkit-box-sizing: border-box; + /* Safari/Chrome, other WebKit */ + -moz-box-sizing: border-box; + /* Firefox, other Gecko */ + box-sizing: border-box; + /* Opera/IE 8+ */ + height: 100% +} + +p { + margin: 0px; +} + +canvas { + position: absolute; +} + +#toolbar { + display: flex; + flex-flow: column; + height: 100%; + + position: absolute; + padding: 0px 20px 0px 20px; + width: 500px; + height: 100vh; + background-color: rgb(189, 189, 189); +} + +#custom { + display: flex; + flex-flow: column; + height: 100%; + + /* position: absolute; */ + padding: 0px 20px 0px 20px; + /* width: 500px; */ + /* height: 100vh; */ + background-color: rgb(189, 189, 189); +} + +.button { + display: block; + position: absolute; + right: 20px; + z-index: 100; +} + + +.controls { + display: flex; + margin: 8px 0px; +} + +.controlFrameButton { + width: 8%; +} +.controlPauseButton { + width: 80%; + margin: auto; +} +/* + */ + +/* CSS */ +.button-8 { + background-color: #e1ecf4; + border-radius: 3px; + border: 1px solid #7aa7c7; + box-shadow: rgba(255, 255, 255, .7) 0 1px 0 0 inset; + box-sizing: border-box; + color: #1f3f55; + cursor: pointer; + display: inline-block; + /* font-family: -apple-system,system-ui,"Segoe UI","Liberation Sans",sans-serif; */ + font-size: 13px; + font-weight: 400; + line-height: 1.15385; + /* margin: 0; */ + outline: none; + padding: 8px .8em; + position: relative; + text-align: center; + text-decoration: none; + user-select: none; + -webkit-user-select: none; + touch-action: manipulation; + vertical-align: baseline; + white-space: nowrap; +} + +.button-8:hover, +.button-8:focus { + background-color: #b3d3ea; + color: #2c5777; +} + +.button-8:focus { + box-shadow: 0 0 0 4px rgba(0, 149, 255, .15); +} + +.button-8:active { + background-color: #a0c7e4; + box-shadow: none; + color: #2c5777; +} + +.buttonReset{ + background-color: #f4e1e1; +} \ No newline at end of file diff --git a/rfid/index.html b/rfid/index.html new file mode 100644 index 0000000..c5306aa --- /dev/null +++ b/rfid/index.html @@ -0,0 +1,58 @@ + + + + + + Document + + + + + +
+
+ +
+
+

Controls:

+

+ Press "Space" to pause and start the animation +

+

+ Press "P" to show/hide the control panel +

+
+

Degrees Per Second

+ +
+

Controls

+
+ + + +
+ +
+
+ +
+ + + + + + + + \ No newline at end of file diff --git a/rfid/js/helper.js b/rfid/js/helper.js new file mode 100644 index 0000000..5955557 --- /dev/null +++ b/rfid/js/helper.js @@ -0,0 +1,284 @@ +async function fetchConfig(className) { + // const config = await $.getJSON("config.json"); + const config = { + PolyTwistColourWidth: [ + { type: "range", min: 3, max: 10, defaultValue: 5, property: "sides" }, + { type: "range", min: 1, max: 600, defaultValue: 400, property: "width" }, + { type: "range", min: 1, max: 100, defaultValue: 50, property: "depth" }, + { type: "range", min: -180, max: 180, defaultValue: -90, property: "rotation" }, + { type: "color", defaultValue: "#4287f5", property: "colour1" }, + { type: "color", defaultValue: "#42f57b", property: "colour2" }, + ], + FloralPhyllo: [ + { type: "range", min: 1, max: 600, defaultValue: 300, property: "width" }, + { type: "range", min: 1, max: 100, defaultValue: 50, property: "depth" }, + { type: "color", defaultValue: "#4287f5", property: "colour1" }, + { type: "color", defaultValue: "#4287f5", property: "colour2" }, + ], + Spiral1: [ + { type: "range", min: 1, max: 50, defaultValue: 20, property: "sides" }, + { type: "range", min: 1, max: 600, defaultValue: 240, property: "width" }, + { type: "color", defaultValue: "#4287f5", property: "colour" }, + ], + FloralAccident: [ + { type: "range", min: 1, max: 50, defaultValue: 20, property: "sides" }, + { type: "range", min: 1, max: 600, defaultValue: 240, property: "width" }, + { type: "color", defaultValue: "#4287f5", property: "colour" }, + ], + FloralPhyllo_Accident: [ + { type: "range", min: 1, max: 50, defaultValue: 20, property: "sides" }, + { type: "range", min: 1, max: 600, defaultValue: 240, property: "width" }, + { type: "color", defaultValue: "#2D81FC", property: "colour1" }, + { type: "color", defaultValue: "#FC0362", property: "colour2" }, + ], + Nodal_expanding: [ + { type: "range", min: 1, max: 100, defaultValue: 5, property: "expand" }, + { type: "range", min: 1, max: 100000, defaultValue: 100000, property: "points" }, + { type: "range", min: 1, max: 10, defaultValue: 3, property: "line_width" }, + { type: "color", defaultValue: "#2D81FC", property: "colour1" }, + { type: "color", defaultValue: "#FC0362", property: "colour2" }, + { type: "range", min: 0, max: 10, defaultValue: 5, property: "colour_change" }, + ], + Nodal: [ + { type: "range", min: 1, max: 1000, defaultValue: 400, property: "width" }, + { type: "range", min: 1, max: 20, defaultValue: 10, property: "points" }, + { type: "range", min: 1, max: 10, defaultValue: 3, property: "line_width" }, + { type: "range", min: 1, max: 20, defaultValue: 1, property: "step" }, + { type: "color", defaultValue: "#2D81FC", property: "colour" }, + ], + Phyllotaxis: [ + { type: "range", min: 1, max: 40, defaultValue: 24, property: "width" }, + { type: "range", min: 1, max: 1000, defaultValue: 300, property: "nMax" }, + { type: "color", defaultValue: "#2D81FC", property: "colour1" }, + { type: "color", defaultValue: "#FC0362", property: "colour2" }, + ], + SquareTwist_angle: [ + { type: "range", min: 1, max: 800, defaultValue: 400, property: "width" }, + { type: "range", min: 1, max: 10, defaultValue: 1, property: "line_width" }, + { type: "color", defaultValue: "#2D81FC", property: "colour1" }, + ], + rectangle_pattern1: [ + { type: "range", min: 1, max: 800, defaultValue: 400, property: "width" }, + { type: "range", min: 1, max: 100, defaultValue: 10, property: "squares" }, + { type: "range", min: 1, max: 10, defaultValue: 1, property: "line_width" }, + { type: "color", defaultValue: "#2D81FC", property: "colour1" }, + ], + EyePrototype: [ + { type: "range", min: 1, max: 800, defaultValue: 400, property: "width" }, + { type: "range", min: 1, max: 100, defaultValue: 10, property: "squares" }, + { type: "range", min: 1, max: 10, defaultValue: 1, property: "line_width" }, + { type: "color", defaultValue: "#2D81FC", property: "colour1" }, + ], + }; + return config[className]; +} + +function addControl(item, instance) { + // console.log(item); + let parentDiv = document.getElementById("custom"); + + let title = document.createElement("p"); + title.innerText = item.property + ": " + item.defaultValue; + title.id = "elText" + item.property; + + let control = document.createElement("input"); + control.type = item.type; + + if (item.type === "range") { + control.min = item.min; + control.max = item.max; + } + + control.value = item.defaultValue; + control.className = "control"; + control.id = "el" + item.property; + + const listener = (event) => { + const newValue = event.target.value; + instance[item.property] = + item.type === "range" ? parseInt(newValue, 10) : newValue; + + title.innerText = item.property + ": " + newValue; + }; + + control.addEventListener("input", listener); + + parentDiv.appendChild(title); + parentDiv.appendChild(control); + + return { element: control, listener }; +} + +function drawEyelid(width, x1, y1, colour) { + x1 -= centerX; + y1 -= centerY; + + const angle = Math.atan2(y1, x1); + const cosAngle = Math.cos(angle); + const sinAngle = Math.sin(angle); + + const x2 = cosAngle * width; + const y2 = sinAngle * width; + + const x3Old = width / 2; + const y3Old = width / 2; + const x4Old = width / 2; + const y4Old = -width / 2; + + const x3 = x3Old * cosAngle - y3Old * sinAngle; + const y3 = x3Old * sinAngle + y3Old * cosAngle; + const x4 = x4Old * cosAngle - y4Old * sinAngle; + const y4 = x4Old * sinAngle + y4Old * cosAngle; + + x1 += centerX; + y1 += centerY; + const x2Final = x2 + x1; + const y2Final = y2 + y1; + const x3Final = x3 + x1; + const y3Final = y3 + y1; + const x4Final = x4 + x1; + const y4Final = y4 + y1; + + ctx.beginPath(); + ctx.moveTo(x1, y1); + ctx.quadraticCurveTo(x3Final, y3Final, x2Final, y2Final); + + ctx.moveTo(x1, y1); + ctx.quadraticCurveTo(x4Final, y4Final, x2Final, y2Final); + ctx.fillStyle = colour; + ctx.fill(); + + ctx.lineWidth = 2; + ctx.strokeStyle = "black"; + ctx.stroke(); +} + +function drawEyelidAccident(x1, y1) { + let leafWidth = 120; + let leafHeight = 60; + x1 -= centerX; + y1 -= centerY; + let angle = Math.atan(y1 / x1); + // if(angle >=Math.PI){ + // angle -=Math.PI + // console.log("greater called") + // } + angle = Math.abs(angle); + let x2Old = 0 + leafWidth; + let y2Old = 0; + + let x3Old = 0 + leafWidth / 2; + let y3Old = 0 + leafHeight / 2; + + let x4Old = 0 + leafWidth / 2; + let y4Old = 0 - leafHeight / 2; + + let x2 = x2Old * Math.cos(angle) - y2Old * Math.sin(angle); + let y2 = x2Old * Math.sin(angle) + y2Old * Math.cos(angle); + + let x3 = x3Old * Math.cos(angle) - y3Old * Math.sin(angle); + let y3 = x3Old * Math.sin(angle) + y3Old * Math.cos(angle); + + let x4 = x4Old * Math.cos(angle) - y4Old * Math.sin(angle); + let y4 = x4Old * Math.sin(angle) + y4Old * Math.cos(angle); + + let oldx1 = x1; + let oldy1 = y1; + + x1 += centerX; // +x2/2 + y1 += centerY; // +x2/2 + x2 += x1; + y2 += y1; + x3 += x1; + y3 += y1; + x4 += x1; + y4 += y1; + ctx.beginPath(); + ctx.moveTo(x1, y1); + ctx.quadraticCurveTo(x3, y3, x2, y2); + + ctx.moveTo(x1, y1); + ctx.quadraticCurveTo(x4, y4, x2, y2); + ctx.fillStyle = "black"; + ctx.fill(); + + ctx.lineWidth = 1; + ctx.beginPath(); + ctx.moveTo(x1, y1); + ctx.quadraticCurveTo(x3, y3, x2, y2); + + ctx.moveTo(x1, y1); + ctx.quadraticCurveTo(x4, y4, x2, y2); + ctx.strokeStyle = "orange"; + ctx.stroke(); +} + +function DrawPolygon(sides, width, rotation, colour) { + ctx.beginPath(); + ctx.moveTo( + centerX + width * Math.cos((rotation * Math.PI) / 180), + centerY + width * Math.sin((rotation * Math.PI) / 180) + ); + + for (var i = 1; i <= sides; i += 1) { + ctx.lineTo( + centerX + + width * + Math.cos((i * 2 * Math.PI) / sides + (rotation * Math.PI) / 180), + centerY + + width * Math.sin((i * 2 * Math.PI) / sides + (rotation * Math.PI) / 180) + ); + } + ctx.strokeStyle = colour; + ctx.lineWidth = 3; + ctx.stroke(); +} + +function rad(degrees) { + return (degrees * Math.PI) / 180; +} + +function colourToText(colour) { + return "rgb(" + colour[0] + "," + colour[1] + "," + colour[2] + ")"; +} + +function LerpHex(a, b, amount) { + var ah = parseInt(a.replace(/#/g, ""), 16), + ar = ah >> 16, + ag = (ah >> 8) & 0xff, + ab = ah & 0xff, + bh = parseInt(b.replace(/#/g, ""), 16), + br = bh >> 16, + bg = (bh >> 8) & 0xff, + bb = bh & 0xff, + rr = ar + amount * (br - ar), + rg = ag + amount * (bg - ag), + rb = ab + amount * (bb - ab); + + return ( + "#" + (((1 << 24) + (rr << 16) + (rg << 8) + rb) | 0).toString(16).slice(1) + ); +} + +function LerpRGB(a, b, t) { + if (t < 0) { + t *= -1; + } + var newColor = [0, 0, 0]; + newColor[0] = a[0] + (b[0] - a[0]) * t; + newColor[1] = a[1] + (b[1] - a[1]) * t; + newColor[2] = a[2] + (b[2] - a[2]) * t; + return newColor; +} + +function render_clear() { + ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); + ctx.fillStyle = "black"; + ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height); +} + +function render_clear() { + ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); + ctx.fillStyle = "black"; + ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height); +} diff --git a/rfid/js/index.js b/rfid/js/index.js new file mode 100644 index 0000000..8138057 --- /dev/null +++ b/rfid/js/index.js @@ -0,0 +1,319 @@ +//jshint esversion:8 +var seed = cyrb128("813311281"); +var rand = sfc32(seed[0], seed[1], seed[2], seed[3]); + +var gateway = `ws://192.168.20.16/ws`; +var websocket; +window.addEventListener('load', onLoad); +function initWebSocket() { + console.log('Trying to open a WebSocket connection...'); + websocket = new WebSocket(gateway); + websocket.onopen = onOpen; + websocket.onclose = onClose; + websocket.onmessage = onMessage; // <-- add this line +} +function onOpen(event) { + console.log('Connection opened'); +} +function onClose(event) { + console.log('Connection closed'); + setTimeout(initWebSocket, 2000); +} +function onMessage(event) { + console.log(event.data) + console.log("--") + setSeed(event.data) + Reset() + updateDrawObj() + // TogglePause() +} + +function onLoad(event) { + initWebSocket(); +} + +function setSeed(val){ + seed = cyrb128(val+"1"); + rand = sfc32(seed[0], seed[1], seed[2], seed[3]); +} + +let c = document.getElementById("myCanvas"); +let ctx = c.getContext("2d"); +ctx.canvas.width = window.innerWidth; +ctx.canvas.height = window.innerHeight; +centerX = ctx.canvas.width / 2; +centerY = ctx.canvas.height / 2; + + +let deg_per_sec = 5; +let targetFps = 60; +let frameDuration = 1000 / targetFps; + +let rotation = 0; //was = j = angle +let paused = true; +render_clear(); + +let drawObj = null; +const classMap = { + PolyTwistColourWidth: PolyTwistColourWidth, + FloralPhyllo: FloralPhyllo, + Spiral1: Spiral1, + FloralAccident: FloralAccident, + FloralPhyllo_Accident: FloralPhyllo_Accident, + Nodal_expanding: Nodal_expanding, + Nodal: Nodal, + Phyllotaxis: Phyllotaxis, + SquareTwist_angle: SquareTwist_angle, + rectangle_pattern1: rectangle_pattern1, + EyePrototype: EyePrototype, + // Add more class constructors here as needed +}; +function createInstance(className, args) { + + if (classMap.hasOwnProperty(className)) { + return new classMap[className](...args); + } else { + throw new Error(`Unknown class name: ${className}`); + } +} + + + +function cyrb128(str) { + let h1 = 1779033703, h2 = 3144134277, + h3 = 1013904242, h4 = 2773480762; + for (let i = 0, k; i < str.length; i++) { + k = str.charCodeAt(i); + h1 = h2 ^ Math.imul(h1 ^ k, 597399067); + h2 = h3 ^ Math.imul(h2 ^ k, 2869860233); + h3 = h4 ^ Math.imul(h3 ^ k, 951274213); + h4 = h1 ^ Math.imul(h4 ^ k, 2716044179); + } + h1 = Math.imul(h3 ^ (h1 >>> 18), 597399067); + h2 = Math.imul(h4 ^ (h2 >>> 22), 2869860233); + h3 = Math.imul(h1 ^ (h3 >>> 17), 951274213); + h4 = Math.imul(h2 ^ (h4 >>> 19), 2716044179); + return [(h1 ^ h2 ^ h3 ^ h4) >>> 0, (h2 ^ h1) >>> 0, (h3 ^ h1) >>> 0, (h4 ^ h1) >>> 0]; +} +function sfc32(a, b, c, d) { + return function () { + a >>>= 0; b >>>= 0; c >>>= 0; d >>>= 0; + var t = (a + b) | 0; + a = b ^ b >>> 9; + b = c + (c << 3) | 0; + c = (c << 21 | c >>> 11); + d = d + 1 | 0; + t = t + d | 0; + c = c + t | 0; + return (t >>> 0) / 4294967296; + } +} + +function PRNGinRange(min = 0, max = 100) { + // find diff + let difference = max - min; + // generate random number + let randTmp = rand(); + // multiply with difference + randTmp = Math.floor(randTmp * difference); + // add with min value + randTmp = randTmp + min; + return randTmp; +} + +async function createShapeWithRandomProperties(inputNumber, shapeConfig) { + + // const shapeName = Object.keys(shapeConfig)[PRNGinRange(0, Object.keys(shapeConfig).length - 1)]; + const shapeName = Object.keys(shapeConfig)[PRNGinRange(0, Object.keys(shapeConfig).length - 1)]; + const ShapeClass = classMap[shapeName]; + const config = await fetchConfig(shapeName); + const properties = {}; + console.log(config) + + config.forEach((item, index) => { + const min = item.min || 0; + const max = item.max || 1; + const randomValue = PRNGinRange(min, max); + // console.log(PRNGinRange(1, 100)) + properties[item.property] = item.type === "color" ? "#4287f5" : Math.round(randomValue); + }); + + return new ShapeClass(...Object.values(properties)); +} + +async function updateDrawObj() { + const shapeSelector = document.getElementById("shape-selector"); + const selectedShape = shapeSelector.value; + const configControls = await fetchConfig(selectedShape); + if (drawObj) { + drawObj.remove(); // Remove the previous instance + } + // Extract default values from the configuration + const defaultValues = configControls + // .filter((item) => item.type !== "color") // Exclude color inputs + .map((item) => item.defaultValue); + + + // drawObj = createInstance(selectedShape, defaultValues); + drawObj = await createShapeWithRandomProperties(813311281, config1); + console.log(drawObj) + drawObj.initialise(configControls); +} + +updateDrawObj(); +const config1 = { + PolyTwistColourWidth: [ + { type: "range", min: 3, max: 10, defaultValue: 5, property: "sides" }, + { type: "range", min: 1, max: 600, defaultValue: 400, property: "width" }, + { type: "range", min: 1, max: 100, defaultValue: 50, property: "depth" }, + { + type: "range", + min: -180, + max: 180, + defaultValue: -90, + property: "rotation", + }, + { type: "color", defaultValue: "#4287f5", property: "colour1" }, + { type: "color", defaultValue: "#42f57b", property: "colour2" }, + ], + FloralPhyllo: [ + { type: "range", min: 1, max: 600, defaultValue: 300, property: "width" }, + { type: "range", min: 1, max: 100, defaultValue: 50, property: "depth" }, + { type: "color", defaultValue: "#4287f5", property: "colour1" }, + { type: "color", defaultValue: "#4287f5", property: "colour2" }, + ], + Spiral1: [ + { type: "range", min: 1, max: 50, defaultValue: 20, property: "sides" }, + { type: "range", min: 1, max: 600, defaultValue: 240, property: "width" }, + { type: "color", defaultValue: "#4287f5", property: "colour" }, + ], + FloralAccident: [ + { type: "range", min: 1, max: 50, defaultValue: 20, property: "sides" }, + { type: "range", min: 1, max: 600, defaultValue: 240, property: "width" }, + { type: "color", defaultValue: "#4287f5", property: "colour" }, + ], + FloralPhyllo_Accident: [ + { type: "range", min: 1, max: 50, defaultValue: 20, property: "sides" }, + { type: "range", min: 1, max: 600, defaultValue: 240, property: "width" }, + { type: "color", defaultValue: "#2D81FC", property: "colour1" }, + { type: "color", defaultValue: "#FC0362", property: "colour2" }, + ], + Nodal_expanding: [ + { type: "range", min: 1, max: 100, defaultValue: 5, property: "expand" }, + { type: "range", min: 1, max: 100000, defaultValue: 100000, property: "points" }, + { type: "range", min: 1, max: 10, defaultValue: 3, property: "line_width" }, + { type: "color", defaultValue: "#2D81FC", property: "colour1" }, + { type: "color", defaultValue: "#FC0362", property: "colour2" }, + { type: "range", min: 0, max: 10, defaultValue: 5, property: "colour_change" }, + ], + Nodal: [ + { type: "range", min: 1, max: 1000, defaultValue: 400, property: "width" }, + { type: "range", min: 1, max: 20, defaultValue: 10, property: "points" }, + { type: "range", min: 1, max: 10, defaultValue: 3, property: "line_width" }, + { type: "range", min: 1, max: 20, defaultValue: 1, property: "step" }, + { type: "color", defaultValue: "#2D81FC", property: "colour" }, + ], + Phyllotaxis: [ + { type: "range", min: 1, max: 40, defaultValue: 24, property: "width" }, + { type: "range", min: 1, max: 1000, defaultValue: 300, property: "nMax" }, + { type: "color", defaultValue: "#2D81FC", property: "colour1" }, + { type: "color", defaultValue: "#FC0362", property: "colour2" }, + ], + SquareTwist_angle: [ + { type: "range", min: 1, max: 800, defaultValue: 400, property: "width" }, + { type: "range", min: 1, max: 10, defaultValue: 1, property: "line_width" }, + { type: "color", defaultValue: "#2D81FC", property: "colour1" }, + ], + rectangle_pattern1: [ + { type: "range", min: 1, max: 800, defaultValue: 400, property: "width" }, + { type: "range", min: 1, max: 100, defaultValue: 10, property: "squares" }, + { type: "range", min: 1, max: 10, defaultValue: 1, property: "line_width" }, + { type: "color", defaultValue: "#2D81FC", property: "colour1" }, + ], + EyePrototype: [ + { type: "range", min: 1, max: 800, defaultValue: 400, property: "width" }, + { type: "range", min: 1, max: 100, defaultValue: 10, property: "squares" }, + { type: "range", min: 1, max: 10, defaultValue: 1, property: "line_width" }, + { type: "color", defaultValue: "#2D81FC", property: "colour1" }, + ], +}; +function render() { + setTimeout(() => { + requestAnimationFrame(() => { + render_clear(); + if (drawObj) { + drawObj.draw(rotation); + } + + if (!paused) { + rotation += deg_per_sec / targetFps; + } + }); + + render(); + }, frameDuration); +} + +document + .getElementById("shape-selector") + .addEventListener("change", updateDrawObj); + +let toolbarShowing = true; +document.addEventListener("keydown", toggleSettings); + +function manualToggleSettings() { + console.log("hi") + toolbarShowing = !toolbarShowing; + let tb = document.getElementById("toolbar"); + if (toolbarShowing) { + tb.style.display = "flex"; + } else { + tb.style.display = "none"; + } +} + +function toggleSettings(e) { + if (e.key == "p") { + toolbarShowing = !toolbarShowing; + } + if (e.code === "Space") { + paused = !paused; + } + + let tb = document.getElementById("toolbar"); + if (toolbarShowing) { + tb.style.display = "flex"; + } else { + tb.style.display = "none"; + } +} + +function TogglePause() { + let pb = document.getElementById("pauseButton"); + paused = !paused; + + if (paused) { + pb.textContent = "Play"; + } else { + pb.textContent = "Pause"; + } +} +function Reset() { + rotation = 0; //was = j = angle + currentFrame = 0; +} + +function ForwardFrame() { + rotation += deg_per_sec / fps; // was = j = innerRotation, now = rotation + currentFrame += 1; // was = i +} +function BackwardFrame() { + rotation -= deg_per_sec / fps; // was = j = innerRotation, now = rotation + currentFrame -= 1; // was = i +} + +function ChangeDegPerSec(newValue) { + deg_per_sec = newValue; +} + +window.onload = render; diff --git a/rfid/js/math.js b/rfid/js/math.js new file mode 100644 index 0000000..f9eeea3 --- /dev/null +++ b/rfid/js/math.js @@ -0,0 +1,77 @@ +function rotateMatrix2d(p, angle) { + // cos0 sin0 + // -sin0 cos0 + const angleD = rad(angle); + const r = [ + [Math.cos(angleD), Math.sin(angleD)], + [-Math.sin(angleD), Math.cos(angleD)], + ]; + const newPoint = [ + p[0] * r[0][0] + p[1] * r[0][1], + p[0] * r[1][0] + p[1] * r[1][1], + ]; + return newPoint; +} + +function rotateMatrix3dX(p, angle) { + // cos0 sin0 + // -sin0 cos0 + const angleD = rad(angle); + const r = [ + [1, 0, 0], + [0, Math.cos(angleD), -Math.sin(angleD)], + [0, Math.sin(angleD), Math.cos(angleD)], + ]; + const newPoint = [ + p[0] * r[0][0] + p[1] * r[0][1] + p[2] * r[0][2], + p[0] * r[1][0] + p[1] * r[1][1] + p[2] * r[1][2], + p[0] * r[2][0] + p[1] * r[2][1] + p[2] * r[2][2], + ]; + return newPoint; +} + +function rotateMatrix3dY(p, angle) { + // cos0 sin0 + // -sin0 cos0 + const angleD = rad(angle); + const r = [ + [Math.cos(angleD), 0, Math.sin(angleD)], + [0, 1, 0], + [-Math.sin(angleD), 0, Math.cos(angleD)], + ]; + const newPoint = [ + p[0] * r[0][0] + p[1] * r[0][1] + p[2] * r[0][2], + p[0] * r[1][0] + p[1] * r[1][1] + p[2] * r[1][2], + p[0] * r[2][0] + p[1] * r[2][1] + p[2] * r[2][2], + ]; + return newPoint; +} +function rotateMatrix3dZ(p, angle) { + // cos0 sin0 + // -sin0 cos0 + const angleD = rad(angle); + const r = [ + [Math.cos(angleD), -Math.sin(angleD), 0], + [Math.sin(angleD), Math.cos(angleD), 0], + [0, 0, 1], + ]; + const newPoint = [ + p[0] * r[0][0] + p[1] * r[0][1] + p[2] * r[0][2], + p[0] * r[1][0] + p[1] * r[1][1] + p[2] * r[1][2], + p[0] * r[2][0] + p[1] * r[2][1] + p[2] * r[2][2], + ]; + return newPoint; +} + +function projectionOrth(v) { + const p = [ + [1, 0, 0], + [0, 1, 0], + ]; + + const nPoint = [ + p[0][0] * v[0] + p[0][1] * v[1] + p[0][2] * v[2], + p[1][0] * v[0] + p[1][1] * v[1] + p[1][2] * v[2], + ]; + return nPoint; +} diff --git a/rfid/js/objects.js b/rfid/js/objects.js new file mode 100644 index 0000000..e070318 --- /dev/null +++ b/rfid/js/objects.js @@ -0,0 +1,449 @@ +class BaseShape { + constructor() { + this.controls = []; // Keep track of created elements and event listeners + } + + initialise(config) { + for (let item of config) { + const { element, listener } = addControl(item, this); + this.controls.push({ element, listener }); + } + } + + remove() { + this.controls.forEach(({ element, listener }) => { + if (element && listener) { + element.removeEventListener("input", listener); + } + if (element && element.parentElement) { + element.parentElement.removeChild(element); + const titleElement = document.getElementById("elText" + element.id.slice(2)); + titleElement.parentElement.removeChild(titleElement); + } + }); + this.controls = []; + } + + draw() { + throw new Error("Draw function not implemented"); + } +} + +class PolyTwistColourWidth extends BaseShape { + constructor(sides, width, depth, rotation, colour1, colour2) { + super(); + this.sides = sides; + this.width = width; + this.depth = depth; + this.rotation = rotation; + this.colour1 = colour1; + this.colour2 = colour2; + } + + draw(innerRotation) { + let out_angle = 0; + const innerAngle = 180 - ((this.sides - 2) * 180) / this.sides; + const scopeAngle = innerRotation - (innerAngle * Math.floor(innerRotation / innerAngle)); + + if (scopeAngle < innerAngle / 2) { + out_angle = innerAngle / (2 * Math.cos((2 * Math.PI * scopeAngle) / (3 * innerAngle))) - innerAngle / 2; + } else { + out_angle = -innerAngle / (2 * Math.cos(((2 * Math.PI) / 3) - ((2 * Math.PI * scopeAngle) / (3 * innerAngle)))) + (innerAngle * 3) / 2; + } + let minWidth = Math.sin(rad(innerAngle / 2)) * (0.5 / Math.tan(rad(innerAngle / 2))) * 2; + + let widthMultiplier = minWidth / Math.sin(Math.PI / 180 * (90 + innerAngle / 2 - out_angle + innerAngle * Math.floor(out_angle / innerAngle))); + + for (let i = 0; i < this.depth; i++) { + const fraction = i / this.depth; + const ncolour = LerpHex(this.colour1, this.colour2, fraction); + DrawPolygon(this.sides, this.width * widthMultiplier ** i, out_angle * i + this.rotation, ncolour); + } + } +} +class FloralPhyllo extends BaseShape { + constructor(width, depth, colour1, colour2) { + super(); + this.width = width; + this.depth = depth; + this.colour1 = colour1; + this.colour2 = colour2; + } + + draw(angle) { + // var c = 24; //something to do with width. but not width + var c = 1; //something to do with width. but not width + //dont make larger than 270 unless altering the number of colours in lerpedColours + for (let n = 200; n > 0; n -= 1) { + const a = n * angle / 1000; //137.5; + const r = c * Math.sqrt(n); + const x = r * Math.cos(a) + centerX; + const y = r * Math.sin(a) + centerY; + + drawEyelid(n * 2.4 + 40, x, y, this.colour1); + } + } +} +class Spiral1 extends BaseShape { + constructor(sides, width, colour) { + super(); + this.sides = sides; + this.width = width; + this.colour = colour; + } + + draw(rotation) { + var rot = Math.round((this.sides - 2) * 180 / this.sides * 2) + var piv = 360 / this.sides; + var stt = 0.5 * Math.PI - rad(rot) //+ rad(rotation); + var end = 0; + var n = this.width / ((this.width / 10) * (this.width / 10)) //pixel correction for mid leaf + + for (let i = 1; i < this.sides + 1; i++) { + end = stt + rad(rot); + + ctx.beginPath(); + ctx.arc(centerX + Math.cos(rad(90 + piv * i + rotation)) * this.width, centerY + Math.sin(rad(90 + piv * i + rotation)) * this.width, this.width, stt + rad(rotation) - (stt - end) / 2, end + rad(rotation) + rad(n), 0); + ctx.strokeStyle = this.colour; + ctx.stroke(); + + + ctx.beginPath(); + ctx.arc(centerX + Math.cos(rad(90 + piv * i - rotation)) * this.width, centerY + Math.sin(rad(90 + piv * i - rotation)) * this.width, this.width, stt - rad(rotation), end - (end - stt) / 2 + rad(n) - rad(rotation), 0); + ctx.strokeStyle = this.colour; + ctx.stroke(); + + + stt = end + -(rad(rot - piv)) //+rad(30); + } + + } +} + +class FloralAccident extends BaseShape { + constructor(sides, width, colour) { + super(); + this.sides = sides; + this.width = width; + this.colour = colour; + } + + draw(rotation) { + var rot = Math.round((this.sides - 2) * 180 / this.sides * 2) + var piv = 360 / this.sides; + var stt = 0.5 * Math.PI - rad(rot) //+ rad(rotation); + var end = 0; + var n = this.width / ((this.width / 10) * (this.width / 10)) //pixel correction for mid leaf + + for (let i = 1; i < this.sides + 1; i++) { + end = stt + rad(rot); + + ctx.beginPath(); + ctx.arc(centerX + Math.cos(rad(90 + piv * i + rotation)) * this.width, centerY + Math.sin(rad(90 + piv * i + rotation)) * this.width, this.width, stt - (stt - end + rad(rotation)) / 2, end + rad(n), 0); + ctx.strokeStyle = this.colour; + ctx.stroke(); + + + ctx.beginPath(); + ctx.arc(centerX + Math.cos(rad(90 + piv * i - rotation)) * this.width, centerY + Math.sin(rad(90 + piv * i - rotation)) * this.width, this.width, stt, end - (end - stt - rad(rotation)) / 2 + rad(n), 0); + ctx.strokeStyle = this.colour; + ctx.stroke(); + + + stt = end + -(rad(rot - piv)) //+rad(30); + } + + } +} +class FloralPhyllo_Accident extends BaseShape { + constructor(sides, width, colour1, colour2) { + super(); + this.sides = sides; + this.width = width; + this.colour1 = colour1; + this.colour2 = colour2; + } + + draw(angle) { + + var c = 24; //something to do with width. but not width + + for (let n = 0; n < 300; n += 1) { + let ncolour = LerpHex(this.colour1, this.colour2, Math.cos(rad(n / 2))); + let a = n * (angle / 1000 + 100); //137.5; + let r = c * Math.sqrt(n); + let x = r * Math.cos(a) + centerX; + let y = r * Math.sin(a) + centerY; + + drawEyelidAccident(x, y); + + } + } +} +class Nodal_expanding extends BaseShape { + constructor(expand, points, line_width, colour1, colour2, colour_change) { + super(); + this.expand = expand; + this.points = points; + this.line_width = line_width; + this.colour1 = colour1; + this.colour2 = colour2; + this.colour_change = colour_change + } + + draw(step) { + let colour_change = this.colour_change / 10 + var angle = 360 / this.points * step + + var start_angle = angle; + var done = false; + var total_moves = 1; + var length = this.expand; + + for (let z = 1; z <= 100; z++) { //why specifically 2500 + ctx.beginPath(); + let ncolour = LerpHex(this.colour1, this.colour2, Math.cos(rad(z * colour_change))); + + ctx.moveTo(centerX + (Math.cos(rad(angle * (z - 1) + 0)) * (length - this.expand)), centerY + (Math.sin(rad(angle * (z - 1) + 0)) * (length - this.expand))); + ctx.lineTo(centerX + (Math.cos(rad(angle * z + 0)) * length), centerY + (Math.sin(rad(angle * z + 0)) * length)); + length += this.expand; + ctx.lineWidth = this.line_width;//try 1 + ctx.strokeStyle = ncolour; + // ctx.strokeStyle = colourToText(ncolour); + console.log(ncolour) + ctx.stroke(); + } + + + } +} +class Nodal extends BaseShape { + constructor(width, points, line_width, step, colour) { + super(); + this.width = width; + this.points = points; + this.line_width = line_width; + this.step = step; + this.colour = colour; + } + // Draw_nodal(300, 100, 31, rotation, "blue"); + draw(rotate) { + // console.log(rotate) + var angle = 360 / this.points * this.step + ctx.beginPath(); + var start_angle = angle; + var done = false; + var total_moves = 1; + ctx.moveTo(centerX + (Math.cos(rad(angle + rotate)) * this.width), centerY + (Math.sin(rad(angle + rotate)) * this.width)); + + while (done != true) { + if ((total_moves * this.step) % this.points != 0) { + total_moves++ + } + else { + total_moves++ + done = true + } + } + for (let z = 1; z <= total_moves; z++) { + ctx.lineTo(centerX + (Math.cos(rad(angle * z + rotate)) * this.width), centerY + (Math.sin(rad(angle * z + rotate)) * this.width)); + } + ctx.lineWidth = this.line_width;//try 1 + ctx.strokeStyle = this.colour; + ctx.stroke(); + + } +} +class Phyllotaxis extends BaseShape { + constructor(width, nMax, colour1, colour2) { + super(); + this.width = width; + this.nMax = nMax; + this.colour1 = colour1; + this.colour2 = colour2; + } + // Draw_nodal(300, 100, 31, rotation, "blue"); + draw(angle) { + + for (let n = 0; n < this.nMax; n += 1) { + const ncolour = LerpHex(this.colour1, this.colour2, n / this.nMax); + // const ncolour = LerpHex(this.colour1, this.colour2, (n/this.nMax)**2); + const a = n * (angle / 1000)//137.5; + const r = this.width * Math.sqrt(n); + const x = r * Math.cos(a) + centerX; + const y = r * Math.sin(a) + centerY; + + ctx.beginPath(); + ctx.arc(x, y, 8, 0, 2 * Math.PI); + ctx.fillStyle = ncolour; + // ctx.fillStyle = colourToText(ncolour); + ctx.fill(); + // console.log(this.c) + } + + } +} +class SquareTwist_angle extends BaseShape { + constructor(width, line_width, colour1) { + super(); + this.width = width; + this.line_width = line_width; + this.colour1 = colour1; + } + drawSquare(angle, size, colour) { + ctx.save(); + ctx.translate(centerX, centerY)//-(Math.sin(rad(angle)) *centerX)); + ctx.rotate(rad(angle + 180)); + ctx.beginPath(); + ctx.strokeStyle = colour; + ctx.lineWidth = this.line_width; + ctx.rect(-size / 2, -size / 2, size, size); + ctx.stroke(); + ctx.restore(); + } + // DrawSquareTwist_angle(400,0,rotation,"red") + draw(innerRotation) { + let out_angle = innerRotation; + let widthMultiplier = 1 / (2 * Math.sin(Math.PI / 180 * (130 - out_angle + 90 * Math.floor(out_angle / 90)))) + 0.5 + + for (let i = 0; i < 25; i++) { + this.drawSquare(innerRotation * i, this.width * widthMultiplier ** i, this.colour1) + } + + } +} +class rectangle_pattern1 extends BaseShape { + constructor(width, squares, line_width, colour1) { + super(); + this.width = width; + this.squares = squares; + this.line_width = line_width; + this.colour1 = colour1; + } + drawSquare(angle, size, colour) { + ctx.save(); + ctx.translate(centerX, centerY)//-(Math.sin(rad(angle)) *centerX)); + ctx.rotate(rad(angle + 180)); + ctx.beginPath(); + ctx.strokeStyle = colour; + ctx.lineWidth = this.line_width; + ctx.rect(-size / 2, -size / 2, size, size); + ctx.stroke(); + ctx.restore(); + } + // Draw_rectangle_pattern1(rotation, squares, 200, "blue"); + draw(rotation) { + for (let z = 0; z < 360; z += 360 / this.squares) { + this.drawSquare(z + rotation, this.width, this.colour1); + } + } +} +class EyePrototype extends BaseShape { + constructor(width, line_width, colour1) { + super(); + this.width = width; + this.line_width = line_width; + this.colour1 = colour1; + this.step = 0; + this.speed = 8; + this.opening = true; + this.counter = 0; + this.points = [ + [50, 250], + [450, 250], + ]; + this.cooldown = 0; + } + drawEyelid(step) { + ctx.lineWidth = 1; + ctx.beginPath(); + ctx.moveTo(this.points[0][0], this.points[0][1]); + ctx.quadraticCurveTo(250, 250 - step, this.points[1][0], this.points[0][1]); + + ctx.moveTo(this.points[0][0], this.points[0][1]); + ctx.quadraticCurveTo(250, 250 + step, this.points[1][0], this.points[0][1]); + ctx.stroke(); + } + eyelidCut(step) { + // ctx.lineWidth = 1; + let squarePath = new Path2D(); + squarePath.moveTo(this.points[0][0], this.points[0][1]); + squarePath.quadraticCurveTo(250, 250 - step, this.points[1][0], this.points[0][1]); + + squarePath.moveTo(this.points[0][0], this.points[0][1]); + squarePath.quadraticCurveTo(250, 250 + step, this.points[1][0], this.points[0][1]); + + ctx.clip(squarePath); + } + drawGrowEye(step) { + console.log(step) + ctx.strokeStyle = "aqua"; + ctx.beginPath(); + ctx.lineWidth = 5; + ctx.arc(250, 250, step, 0, 2 * Math.PI); + ctx.stroke(); + ctx.strokeStyle = "orange"; + } + drawCircle(step) { + ctx.beginPath(); + ctx.lineWidth = 5; + ctx.arc(250, 250, step, 0, 2 * Math.PI); + ctx.stroke(); + } + stepFunc() { + if (this.cooldown != 0) { + this.cooldown--; + } else { + if (this.opening == true) { + if (this.step >= 200) { + this.cooldown = 200; + this.opening = false; + this.step -= this.speed; + } else { + this.step += this.speed; + } + } else { + if (this.step <= 0) { + this.opening = true; + this.step += this.speed; + } else { + this.step -= this.speed; + } + } + } + } + + draw(rotation) { + console.log(this.counter) + ctx.strokeStyle = "orange"; + ctx.fillStyle = "black"; + // ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); + // ctx.fillRect(0, 0, 500, 500); + + // let newPath = new Path2D(); + // newPath.arc(150, 75, 75, 0, 2 * Math.PI); + + ctx.beginPath(); + ctx.rect(100, 100, 300, 300); + ctx.stroke(); + + this.drawEyelid(this.step); + + ctx.save(); + // squareCut(); + this.eyelidCut(this.step); + + if (this.counter % 100 == 0) { + this.counter = 0; + } + this.drawGrowEye(100 + this.counter); + + this.drawCircle(100); + + ctx.restore(); + + this.stepFunc(); + this.counter++; + } +} + diff --git a/webGl/first test/index.html b/webGl/first test/index.html new file mode 100644 index 0000000..05518d8 --- /dev/null +++ b/webGl/first test/index.html @@ -0,0 +1,21 @@ + + + + + + WebGL Centered Square + + + + + + + \ No newline at end of file diff --git a/webGl/first test/main.js b/webGl/first test/main.js new file mode 100644 index 0000000..04eaaf7 --- /dev/null +++ b/webGl/first test/main.js @@ -0,0 +1,98 @@ +const canvas = document.getElementById('canvas'); +const gl = canvas.getContext('webgl'); + +if (!gl) { + alert('WebGL is not supported in your browser.'); +} + +function resizeCanvas() { + canvas.width = window.innerWidth; + canvas.height = window.innerHeight; + gl.viewport(0, 0, canvas.width, canvas.height); +} + +window.addEventListener('resize', resizeCanvas); +resizeCanvas(); + +const vertices = [ + -0.5, -0.5, + 0.5, -0.5, + 0.5, 0.5, + -0.5, 0.5, +]; + +const vertexBuffer = gl.createBuffer(); +gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); +gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW); + +const vertexShaderSource = ` + attribute vec2 a_position; + + uniform vec2 u_resolution; + uniform vec2 u_translation; + uniform vec2 u_scale; + + void main() { + vec2 scaledPosition = a_position * u_scale; + vec2 position = scaledPosition + u_translation; + + vec2 zeroToOne = position / u_resolution; + vec2 zeroToTwo = zeroToOne * 2.0; + vec2 clipSpace = zeroToTwo - 1.0; + + gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1); + } +`; + +const vertexShader = gl.createShader(gl.VERTEX_SHADER); +gl.shaderSource(vertexShader, vertexShaderSource); +gl.compileShader(vertexShader); + +const fragmentShaderSource = ` + precision mediump float; + + void main() { + gl_FragColor = vec4(1, 0, 0, 1); + } +`; + +const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); +gl.shaderSource(fragmentShader, fragmentShaderSource); +gl.compileShader(fragmentShader); + +const program = gl.createProgram(); +gl.attachShader(program, vertexShader); +gl.attachShader(program, fragmentShader); +gl.linkProgram(program); +gl.useProgram(program); + +const positionAttributeLocation = gl.getAttribLocation(program, 'a_position'); +gl.enableVertexAttribArray(positionAttributeLocation); +gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); +gl.vertexAttribPointer(positionAttributeLocation, 2, gl.FLOAT, false, 0, 0); + +const resolutionUniformLocation = gl.getUniformLocation(program, 'u_resolution'); +const translationUniformLocation = gl.getUniformLocation(program, 'u_translation'); +const scaleUniformLocation = gl.getUniformLocation(program, 'u_scale'); + +function drawScene() { + gl.clearColor(0, 0, 0, 1); + gl.clear(gl.COLOR_BUFFER_BIT); + + gl.uniform2f(resolutionUniformLocation, canvas.width, canvas.height); + + const squareWidth = 50; + const squareHeight = 50; + const xCenter = (canvas.width - squareWidth) / 2; + const yCenter = (canvas.height - squareHeight) / 2; + gl.uniform2f(translationUniformLocation, xCenter, yCenter); + + gl.uniform2f(scaleUniformLocation, squareWidth, squareHeight); + + gl.drawArrays(gl.TRIANGLE_FAN, 0, 4); + + requestAnimationFrame(drawScene); +} + +drawScene(); +