diff --git a/README.md b/README.md index 4ac8bbff..f7a927ea 100644 --- a/README.md +++ b/README.md @@ -1,61 +1,24 @@ -Assignment 4 - Creative Coding: Interactive Multimedia Experiences -=== +# Interactive Sphere-ish Visualizer -Due: October 4th, by 11:59 AM. +[https://2usvrz.csb.app/](https://2usvrz.csb.app/) -For this assignment we will focus on client-side development using popular audio/graphics/visualization technologies. The goal of this assignment is to refine our JavaScript knowledge while exploring the multimedia capabilities of the browser. +Note: The project name is a4-cindy-trac. However, codesandbox does not allow me to change the hosting link. I started the assignment by playing around with an example on codesandbox and then struggled to move it over to Glitch. Although I did not use Glitch for hosting, you can still see all the files I authored at this [link](https://codesandbox.io/s/a4-cindy-trac-2usvrz?file=/src/index.js). -[WebAudio + Canvas Tutorial](https://github.com/cs4241-22a/cs4241-22a.github.io/blob/main/using_webaudio_canvas.md) -[SVG + D3 tutorial](https://github.com/cs4241-21a/cs4241-21a.github.io/blob/main/using_svg_and_d3.md) +## Goal -Baseline Requirements ---- +I used the following frameworks and libraries to a visualizer that allows users to have an interactive experience. The user is able to view and edit a geometric shape. +- [Three.js](https://threejs.org/): a library for 3D graphics / VR experiences +- [Tweakpane](https://cocopon.github.io/tweakpane/): a compact pane library to edit parameters and monitor value changes +- [WebGL (Web Graphics Library)](https://cocopon.github.io/tweakpane/): a library for rendering interactive 2D and 3D graphics -Your application is required to implement the following functionalities: +The user can: +- drag to move the shape +- adjust where the camera is +- change the shape color and toggle its wireframe mode +- adjust the position, rotation, and scale of the shape -- A server created using Express. This server can be as simple as needed. -- A client-side interactive experience using at least one of the following web technologies frameworks. - - [Three.js](https://threejs.org/): A library for 3D graphics / VR experiences - - [D3.js](https://d3js.org): A library that is primarily used for interactive data visualizations - - [Canvas](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API): A 2D raster drawing API included in all modern browsers - - [SVG](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API): A 2D vector drawing framework that enables shapes to be defined via XML. - - [Web Audio API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API): An API for audio synthesis, analysis, processing, and file playback. -- A user interface for interaction with your project, which must expose at least four parameters for user control. [tweakpane](https://cocopon.github.io/tweakpane/) is highly recommended for this, but you can also use regular HTML `` tags (the `range` type is useful to create sliders). You might also explore interaction by tracking mouse movement via the `window.onmousemove` event handler in tandem with the `event.clientX` and `event.clientY` properties. Consider using the [Pointer Events API](https://developer.mozilla.org/en-US/docs/Web/API/Pointer_events) to ensure that that both mouse and touch events will both be supported in your app. -- Your application should display basic documentation for the user interface when the application first loads. +## Challenges -The interactive experience should possess a reasonable level of complexity. Some examples: -### Three.js -- A generative algorithm creates simple agents that move through a virtual world. Your interface controls the behavior / appearance of these agents. -- A simple 3D game... you really want this to be a simple as possible or it will be outside the scope of this assignment. -- An 3D audio visualization of a song of your choosing. User interaction should control aspects of the visualization. -### Canvas -- Implement a generative algorithm such as [Conway's Game of Life](https://bitstorm.org/gameoflife/) (or 1D cellular automata) and provide interactive controls. Note that the Game of Life has been created by 100s of people using ; we'll be checking to ensure that your implementation is not a copy of these. -- Design a 2D audio visualizer of a song of your choosing. User interaction should control visual aspects of the experience. -### Web Audio API -- Create a screen-based musical instrument using the Web Audio API. You can use projects such as [Interface.js](http://charlie-roberts.com/interface/) or [Nexus UI](https://nexus-js.github.io/ui/api/#Piano) to provide common musical interface elements, or use dat.GUI in combination with mouse/touch events (use the Pointer Events API). Your GUI should enable users to control aspects of sound synthesis. If you want to use higher-level instruments instead of the raw WebAudio API sounds, consider trying the instruments provided by [Tone.js]() or [Gibber](https://github.com/charlieroberts/gibber.audio.lib). -### D3.js -- Create visualizations using the datasets found at [Awesome JSON Datasets](https://github.com/jdorfman/Awesome-JSON-Datasets). Experiment with providing different visualizations of the same data set, and providing users interactive control over visualization parameters and/or data filtering. Alternatively, create a single visualization with using one of the more complicated techniques shown at [d3js.org](d3js.org) and provide meaningful points of interaction for users. - -Deliverables ---- - -Do the following to complete this assignment: - -1. Implement your project with the above requirements. -3. Test your project to make sure that when someone goes to your main page on Glitch/Heroku/etc., it displays correctly. -4. Ensure that your project has the proper naming scheme `a4-firstname-lastname` so we can find it. -5. Fork this repository and modify the README to the specifications below. *NOTE: If you don't use Glitch for hosting (where we can see the files) then you must include all project files that you author in your repo for this assignment*. -6. Create and submit a Pull Request to the original repo. Name the pull request using the following template: `a4-firstname-lastname`. - -Sample Readme (delete the above when you're ready to submit, and modify the below so with your links and descriptions) ---- - -## Your Web Application Title - -your hosting link e.g. http://a4-charlieroberts.glitch.me - -Include a very brief summary of your project here. Images are encouraged when needed, along with concise, high-level text. Be sure to include: - -- the goal of the application -- challenges you faced in realizing the application -- the instructions you present in the website should be clear enough to use the application, but if you feel any need to provide additional instructions please do so here. +- I originally started playing around with the aforementioned libraries on codesandbox.io. By the time I made significant headway, I struggled to migrate the code over to Glitch with an Express server. +- With this assignment, I was already way past the initial due date. It was a struggle to figure out when to be done with the project. I kept wanting to explore the libraries and implement more features. If I had more brain power to dedicate to this project, I would look into allowing the user to change the radius and number of width/height segments of the geometric shape. +- One thing that surprised me was how nice of a tool Tweakpane is. When I last did a computer graphics project, I would manually create buttons or have to set user actions to different keys. Tweakpane streamlines creating a pane to edit and monitor parameters. diff --git a/index.html b/index.html new file mode 100644 index 00000000..70fe8a9f --- /dev/null +++ b/index.html @@ -0,0 +1,11 @@ + + + + A4 Interactive Sphere-ish Visualizer + + + +
+ + + diff --git a/package.json b/package.json new file mode 100644 index 00000000..562058ad --- /dev/null +++ b/package.json @@ -0,0 +1,22 @@ +{ + "name": "a4-cindy-trac", + "version": "1.0.0", + "description": "", + "main": "index.html", + "scripts": { + "start": "parcel index.html --open", + "build": "parcel build index.html" + }, + "dependencies": { + "parcel-bundler": "^1.6.1", + "three": "0.132.2", + "tweakpane": "3.0.5" + }, + "devDependencies": { + "@babel/core": "7.2.0" + }, + "resolutions": { + "@babel/preset-env": "7.13.8" + }, + "keywords": [] +} diff --git a/server.js b/server.js new file mode 100644 index 00000000..478aa2b2 --- /dev/null +++ b/server.js @@ -0,0 +1,11 @@ +const express = require( 'express' ), + app = express() + +app.use( (req,res,next) => { + console.log( 'url:', req.url ) + next() +}) + +app.get( '/', ( req, res ) => res.send( 'views/index.html' ) ) + +app.listen( process.env.PORT || 3000 ) diff --git a/src/index.js b/src/index.js new file mode 100644 index 00000000..5617e0ba --- /dev/null +++ b/src/index.js @@ -0,0 +1,126 @@ +import * as THREE from "three"; +import { OrbitControls } from "three/examples/jsm/controls/OrbitControls"; +import { Pane } from "tweakpane"; +import "./style.css"; + +let canvas, scene, model, size; +let camera, renderer, cam_controller; + +main(); + +function main() { + console.clear(); + + // size of window + size = { width: window.innerWidth, height: window.innerHeight }; + + // create new scene + scene = new THREE.Scene(); + + // CANVAS + canvas = document.createElement("canvas"); + canvas.setAttribute("class", "webgl"); + document.body.appendChild(canvas); + + // MODELS + model = new THREE.Group(); + + // creating shape and wireframe + const geometry = new THREE.SphereGeometry(1, 10, 5); + const material = new THREE.MeshBasicMaterial({ + color: localStorage.getItem("MODEL_COLOR") || "#FFFFFF", + wireframe: true + }); + const mesh = new THREE.Mesh(geometry, material); + + // CAMERA CONTROLLERS + camera = new THREE.PerspectiveCamera(75, size.width / size.height); + cam_controller = new OrbitControls(camera, canvas); + renderer = new THREE.WebGLRenderer({ canvas: canvas, antialias: true }); + + // CAMERA CONTROLS + cam_controller.enabled = true; + cam_controller.enableDamping = true; + cam_controller.dampingFactor = 0.05; + camera.position.set(0, 0, 2); + + // Setup + model.add(mesh); + scene.add(model); + scene.add(camera); + + // TWEAKPANE SETTINGS + + // create new pane (overall menu) + let pane = new Pane({ + title: "EDIT VISUALIZER", + expanded: true + }); + + // CAMERA SETTINGS drop down + const camPane = pane.addFolder({ + title: "Camera Settings", + expanded: true // opened automatically so user sees all options + }); + + // CAMERA SETTINGS options + // checkbox to enable user to drag shape + camPane.addInput(cam_controller, "enabled", { label: "Enable Drag" }); + + camPane.addSeparator(); + + // input boxes to change camera position + camPane.addInput(model, "position", { + label: "Camera Position", + x: { min: -1, max: 1 }, + y: { min: -1, max: 1 }, + z: { min: -12, max: 1 } + }); + + // OBJECT SETTINGS drop down + const objPane = pane.addFolder({ + title: "Object Settings", + expanded: true // opened automatically so user sees all options + }); + + // change color of shape + objPane + .addInput({ color: material.color.getStyle() }, "color", { + label: "Color", + view: "color" + }) + .on("change", (e) => { + localStorage.setItem("MODEL_COLOR", e.value); + material.color.set(e.value); + }); + + objPane.addSeparator(); + + // change rotation of shape + objPane.addInput(model, "rotation", { label: "Rotation" }); + + // change scale of shape + objPane.addInput(model, "scale", { label: "Scale" }); + + objPane.addSeparator(); + + // checkbox to enable wireframe mode + objPane.addInput(material, "wireframe", { label: "Wireframe Mode" }); + + draw(); +} + +// render function +function render() { + cam_controller.update(); + renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)); + renderer.setSize(size.width, size.height); + + // render scene + renderer.render(scene, camera); +} + +function draw() { + render(); + window.requestAnimationFrame(draw); +} diff --git a/src/style.css b/src/style.css new file mode 100644 index 00000000..c65de0f6 --- /dev/null +++ b/src/style.css @@ -0,0 +1,19 @@ +* { + font-family: sans-serif; + margin: 0; + padding: 0; +} + +canvas.webgl { + position: fixed; + outline: none; + height: 100%; + width: 100%; +} + +body { + height: 100%; + overflow: hidden; + background: #000000; + color: white; +}