SONDER.

Connections Lab - Midterm V2

Project Brief:

Make something cool with node.js, express, websockets, and a database.

Ideation:

I really really really suck at fullstack and backend, dealing with data, security, timing, efficiency deployment etc. I'm very much frontend visuals and graphics oriented in my programming. When trying to think about ideas for this project I literally hopped on a call with my friend getting him to explain what backend truly encapsulated and use cases for express and node.js. I literally needed it spelled out so that I could start coming up with project ideas that would actually use express and a database. My first idea was far too lofty as I didn't realize how soon the second project was due, I toying around with a conceptual immersive web installation based on the end of time. Predicated on the assumption and belief that one of the core purposes/affordances of art is to create and communicate emotional connections. At the end of time users would no longer be able to communicate via speech anymore, instead all user input would be programmatically transformed into abstract visualizations and soundscapes, users would be asked to experiment and tweak their final messages to their likings before sending them off to the void to be viewed by others. It's an idea that I'm still interested in exploring but needs refinement both conceptually and in the logistical planning.

I considered revisiting and old sketch I had made in undergrad where I controlled a 3D model of a plane via my phone, it was a socket.io video game that I never finished developing but used sockets, node and express!...It would have been a cop out of sorts and I have very little interest in video game design at the moment. In my previous project I had virtual buttons laid out on my phone client page and essentially just created a remote virtual keyboard. I toyed with the idea of building on that concept instead of re-using it and exploring phone orientation for controlling 3D avatars. Being able to turn your phone like a wheel to steer your avatar in 3D space etc, an exploration of adding physicality and materiality back to the digital world. I dreamed of recreating Mozilla's VRpainter in three.js with a phone controlling a brush in 3D space! Expectedly, I was growing ever closer to becoming Icarus and trying to fly towards the sun. Luckily before I could get destroyed trying to take on this massive project, it turns out the three.js orientation controls are so rarely used and poorly documented that I never got off the ground! Phew disaster averted.

With 48 hours left and literally no project at hand I revisited a variation of my first project idea, a virtual home containing all my past failures and half finished ideas. My initial idea allowed users to explore the space and click around to download fragments of code and projects for inspiration as well as upload their own unfinished sketches for the public to see and download. A collaborative catharsis that none of us are perfect and get it right the first time, a shared experience of being content in the process. The webpage would check for updates in the server and database and programmatically fill the space with clickable 3D objects based on new submissions. In lieu of the massive security and efficiency risks of having an open datastore for people to upload whatever they want without moderation and potentially exposing users to malicious or unwanted content. I've been on the web enough to know never trust the web! People are awful and will destroy things! Instead, I crafted a narrative around hope and passing on my past work and failures as potential seeds for inspiration and chances to upcycle unfinished work.

Inspiration:

The main inspiration for my project actually came from something fellow IMA student Vince Piccone used to ask during our Friday classes in the summer. Vince would often the visiting speakers how they bounced back from failures or ideas that don't pan out. It really made me reflect on all the folders of half written abandoned code and ideas that I couldn't figure out at the time, lost interest in etc.

Process:

Excuse my language, this was an absolute shit show. 36/48 hrs spent coding without really any guarantee that any of this would work. I was neck deep in unknown territory for me and working against the clock. My first course of action was to create some clickable particles. I experimented with instanced buffer geometries and buffer geometries in general as I had seen examples in Three.js website of numerous hoverable/clickable elements. I wanted to use particles instead because...I'm a sucker for particles and I also wasn't familiar / interested in finding and implementing uniqueID for instance buffers. Originally I wanted the center of the space to be an explosion frozen in time and the clickable elements to be shards of glass/fragments of crystals etc but it turns out there aren't many good free frozen 3D models of explosions online, most of what's available are c4d renders and I'm just not familiar enough with the actual 3d software to use them. Instead, again thinking about the more 'hopeful' narrative I was driving now I decided on using a 3D model of a tree as the center piece and having the particles as a sort of metaphorical fruit or flora. After the base visuals were finished I realized that I hadn't actually touched the core functionality yet and scrambled to search for ways to store image files or zip files on nedb. I found that you can store images as 64bit data but really images aren't projects or code, I needed a way to share projects. I could link people to Github repos but Github doesn't work like youtube. Private repos are truly private and don't have shareable links unlike unlisted videos. I wasn't interested in filling my Github with a bunch of trash repos and it also felt a little anti-climatic? I realized I had no choice but to be bold, go find a datastorage! I wasted a bunch of time with firebase because I didn't understand what it was and what I was looking for! I panicked and looking into AWS s3 buckets! After some fireplace chats with developer friends I realized that I just needed a db to contain links to the storage spaces and items. Realizing that the greatest gift from NYU was a permanent email and unlimited student google drive I realized my cloud storage was under my nose the whole time. I spent the better part of the night trying to learn how to use the drive api and somehow managed to get it working and connected to my sketch. My web application would now check my designated google drive folder for a list of items, return those items view/download links and pass them onto my Three.js sketch and assign each link to a particle to be accessed when clicked. Intending to make things a bit more immersive on a whim I hired a voice actor on fivver to do a 30 second monologue of script I jotted down from the POV of an aging digital curator. An aging version of me getting ready to pass the torch. Add some css keyframe animations, background ambience music and whala I have a 'cinematic' intro to my space. I wanted to add more visuals to clutter the space and really sell the aesthetic of an aging old man with old work scattered everywhere but ran out of time as I spent the better part of a night trying to deploy and host my project on godaddy my shared web hosting eventually having to switch to my own vps server space. Deployment is hard. With that the first rough draft of my project was done! Of course between every single feature implementation I described were about a million bugs and problems and roadblocks and at this very moment I'm fearful that my app will break at any moment. :( 

Problems:

OH BABY HERE WE GO!

  1. Clickable Particles:

On paper this shouldn't be that hard, create a raycaster and then shoot it from your mouse and camera every time someone clicks. See if that raycaster is intersecting with any of the objects and do something or don't do something based on that event. The problem with particles was that when pushing a float32bufferarray of random positions to populate my pointcloud for some reason, when the total range was less than 150 or so the bounding boxes were all messed up. IE, whenever I created a random set of vector3 to hold positions with a range of less than 150, no matter where I clicked my raycaster would somehow intersect even if I clicked in empty space. I still don't know why the phenomena occurred. I considered the possibility that things were hidden behind each other, placed too close or too far so that what I thought was empty space was just populated by a hidden particle. I disproved this theory however by dropping my point population to 3, even when I could visibly see all three of my points and the distance between somehow their bounding boxes would cover the entire space in between! I never figured out what was causing this issue but instead managed to sacrifice a bit of performance to bypass the issue by scaling everything up and increasing the range to 200. Scaling the 3D object is much more expensive to do in application but it is what it is for now.

  1. Databases:

Not considering the sidetracking into firebase as an actual problem actually figuring out the google drive api was quite a battle. Google just assumes you're familiar with api's and developing and really doesn't hold your hand. I like having my hand held! You may look at the drive api documentation and think it's easy to read but to someone like me, it was unfortunately not. It assumes you have a basic knowledge of querying and api authentication keys etc and I just simply don't. As with all big companies they update their api often and tutorials online were more often than not deprecated to an unusable state. I spent a lot of time trying to get the basics of the API to work really w/o a full understanding of refresh tokens vs auth tokens, how long I can use them for etc.

  1. Async/Await:

This is a continuation of my database woes as the the flow of information relied heavily on js promises, asynchronous functions etc. The only problem is that I'm not super familiar with promises and async coding, I ran into a huge number of timing errors simply because I lacked an understanding of when promises get fulfilled and what I can do with the data before and after. I didn't know if my empty array was pending, what that really meant etc, all I knew was that my data was not coming through when I was trying to draw everything.

  1. Deploying:

Truly the biggest nightmare that I didn't see coming at all, I intended to finish up the visuals, add some more textures and fragment esque geometries to my sketch etc after I deployed a version for safety. 5 hours later and 12 hrs before the presentation all I had were a million errors and no deployed sketch. I was using shared hosting via godaddy and information was scarce on how to run a node.js app on shared hosting. There are various 'supposed' solutions and wget grep curl commands that theoretically allow me to download node onto my shared hosting but none of them seemed to work for me. The biggest issue with shared hosting is the lack of root access and ability to add node.js to my server. Obviously without node.js installed I would have no way of getting my app working. After 5 hrs and no success I did some more digging and got a cheap vps server where I had full root access to. It was pretty barebones and didn't have any gui or control panel so I had to dig out my terminal and ssh notes and work everything from the command line. An interesting note is that I found out for whatever reason, some of my dependencies only work on node version 14.18.1, if you have the most up to date version of node you will run into errors!

Code Breakdown:

My different npm modules, nedb, parcel-bundler, drive api, and other global variables I needed.
Some of the functions I wrote for the driveAPI, some parts aren't in use currently, as I had previously mentioned there was an iteration where the dataflow was two ways allowing users to upload their files as well which was scrapped.
I ended up uploading the files by hand but then running a list files function which returns all the files in the shared drive with their names, unique id's and their view/download links. I originally intended for clicks to immediately go to download but I realized that it could be jarring or uncomfortable to click something abstract and have a foreign file get downloaded to your computer. I opted for a slightly less immersive linking to the files themselves to give users the ability to look through the files a bit before choosing to download themselves.
Inside my sockets I'm just looking through the links in my links db and sending them as to newly connected clients. I'm also using parcel-bundler as a middleware for express.
JS interacting with my html elements, when my buttons are clicked they play the audio files of the old curator monologue and the bg music. I don't know why I split the audio into two parts instead of mixing them into one but in future iterations that's what I'll do.
Sockets on my sketch listening for when the link data gets sent and storing it in a global array.
Particle systems using Float32Buffers, I found that directly making Float32bufferArrays didn't work...for some reason? No matter where I clicked within the point cloud it would trigger a hit. I had to user buffer attributes and set the attributes manually.
Raycasting, I raycast on click and them I check for intersections, I have a global variable called counter which increments when there's an intersection, once the counter is greater than the linkdata array's length I reset it to 0 so I don't get an array index out of bounds and so that I can keep clicking and it just loops through. I originally wanted the number of points in the point cloud to be programmatically updated by the length of the array but quickly abandoned that idea as I didn't have time to upload several hundred different files to create a full looking point cloud.
Future Iterations:

I fully intend to clean up the code in coming days when my brain comes back to normal and I pay off my sleep debt, add some more visuals and fix up the bottlenecks to make everything run a bit smoother.

Live Site / Github:

http://72.167.223.17:3001/

https://github.com/fakebrianho/avenueGlitch