More selected projects

Alternia

by: Mike Hobbs

The Project

Alternia is a playable three-dimensional world in which the environment, terrain and laws of physics are randomly generated with each run. Players can travel around the landscape, observing new components with every visit. The world’s content (namely trees, rivers, birds and more) appear with varying abstract characteristics and behaviours depending on variables set when the application is run. The idea for Alternia is that there are no rules, no restrictions, and complete freedom for any new features that may be desired.

You can play Alternia here: igor.doc.gold.ac.uk/~mhobb012/Creative/World/Alternia.html

 

Project Aim

Audience & outcome

Initially, the world was intended to be procedurally generated, and almost solely rely on player interaction and engagement to determine what comes next. However, this would not have adhered to the desires or needs of a wider audience. With Alternia, I wanted to prioritise an initial enjoyable experience exploring the world, but to also impact a user’s decision on potential world creation of their own. The real intended audience was not only someone with an interest in generated scenery, but with a desire to take the idea of a disordered environment and make additions and alterations.

Research

Once I had an objective and an image in mind I set out to explore options for 3D development. I had no prior experience with any form of 3D programming, so started researching into what I need to start making an application. I have always been interested in 3D animation, game design and modelling, but had no idea how it was done.

I started by looking up the applications in which some well-known games were made in. To my surprise, many modern games and mobile applications are made in a cross-platform game engine, Unity. However, Unity was very much focused on interfaced-based design which was not suitable for my project.

Eventually, I came across a video in which a creator had remade the popular video game Star Fox 64 (Nintendo 64, 1997) using a 3D JavaScript library called Three.Js.

Three.Js is an open-source, multi-browser JavaScript API makes use of the web library WebGL to display animated 3D graphics in a browser. WebGL would have been too difficult to use directly, which is the reason three.js was created – to make this process easier on a higher level.

I was intimidated by three.js’s syntax at first but was hopeful when seeing use of the vanilla JavaScript I am comfortable with. By following a start-up guide on the official three.js documentation, I created my first piece of 3D graphics, a rotating cube.

 

Creative Process

My creative process and choices of aesthetic style downgraded from start to end, but finished with the best and most suitable decision.

Originally, I started to create every iteration of a world with textures. I would import various textures and wrap/apply them to each object in a scene. I wanted it to look real. I quickly learned that this was not suitable for my project. Textures from varying sources were inconsistent and didn’t work well together.

A widespread practice amongst 3D graphics is to use shader programs. Shaders produce appropriate levels of light, darkness, texture and colour in an image/object. This would be important in making every object in a scene appear as if they’re from the same place, and help to create realistic looking graphics. I managed to find an excellent water shader. The result was surprisingly realistic when I tested it with my terrain map.

Whilst shaders look great and create a realistic scene, they are also hardware intensive and therefore not suitable. I needed an alternative that retained appealing visuals but without the performance drop.

An art style that is known for its clean and lightweight nature is low-poly graphics. Low-poly graphics are exactly what the name implies, objects with a relatively small number of polygons that make up the mesh. With fewer faces you can still create an aesthetically pleasing graphics. This was my one of my major aesthetic decisions and worked in my favour.

Using less vertices creates simpler objects producing better performance when applied on a large-scale mesh, with minimal cost to shape. It was clean, and gave me more scope for creativity.

As for use of colour, I didn’t want to just have random colours for every entity in the world in each run. I still wanted a sense of consistency in the generated world. Having a theme each time it is run is one way to achieve this. Random colours did not work well, but random themes were effective.

A substantial portion of my development process was trying to find a suitable algorithm for terrain generation. I did not want a realistic and extremely bumpy terrain, instead I wanted something basic with slight alterations, but remaining natural and walkable. I tried a variety of methods, such as using perlin and simplex noise functions, the diamond-square algorithm, and a custom terrain generation method created for three.js development. Some of the results worked well, however would later fail to be compatible with the physics system in the build, and had to be discarded. I settled with my own take on vertex manipulation with some tweaks found in other demos, to create a sinuous plane.

It was good to have attractive objects, but they were all static. I needed animation. The movement or waves of the water is an interesting part of the world. Every world has a water element, which bobs up and down through a river trench and the surrounding ocean. This was as simple as applying a translucent material to the water geometry and updating the z-vertices on every frame (moving up and down). I made use of the sine function for moving back and forth, at a random speed. I used a simple colour material instead of a shader or texture for the water to fit the simple and low-poly theme, but also to avoid it being considered an ocean. It could be water, but it could also be any other liquid. Anything goes in Alternia.

You, the player, cannot be seen. Originally you could see yourself (a box) and even see yourself in the water shader reflection, which, whilst being a notable feature, voids the idea of the project being about the environment.  I did not want there to be a storyline or character in this world, instead just a medium in which to view it.

 

The Build

Considering I had no prior knowledge or experience with three.js, WebGL, or any other form of 3D graphics, it would be some time until I was ready to start working on my final world. It was necessary to first get comfortable with three.js’s syntax and how to setup a basic scene. Applying textures was one of my first problems. Instead of the spinning crate shown previously, the outcome of my first texture attempt was entirely different. One texture was being applied inside the object rather than mapped to each object face, resulting in what looked like a cube mirror reflecting some wood.

To kick-start development, I began by researching into first person movement in three.js. I had seen it before and wanted to try it myself. I decided to use a vanilla JavaScript switch statement for key presses (W, A, S, D) and set callback functions for keydown and keyup events on the browser. I thought that if the camera was moved in the appropriate axis when keys are pressed it would give the impression that you were walking in first-person perspective. This method worked perfectly, but it did not tackle the issue of mouse looking. I tried using three.js’ JavaScript include PointerLockControls, but it did not work with my physics tool. Instead I had to make mouse look and movement from scratch, with maths functions taken from another example.

The largest object in Alternia is the terrain. This caused many issues with physics when I tried various terrain generation functions and algorithms, but soon found a very simple noise function to apply to a plane by manipulating its Z vertices.

Although Alternia has no restrictions, I still wanted some sense of physics in my world. Instead of making my own, I made use of a physics library/tool made specifically for three.js, Physi.js. This allowed me to create completely new objects with the same properties as three.js, but with a plethora of new behaviours, such as gravity and collisions.

Since these objects had their own physics applied, it was difficult to override these with my own changes to their behaviour (for example moving a physi.js player object around), therefore I had to find many workarounds and cheats so that my world and physics would work together.

My final major issue, once I had almost finished the world, was performance. Even on a high-end computer the world was stuttering. It was a difficult problem to tackle, because some seemingly more taxing three.js pieces had no effect. I later discovered that introducing so many three.js meshes at once was the cause. After some research, I found that when adding many objects of the same type to a scene, it was necessary to merge them so that it was all added at once even though it consists of 50+ objects. The only drawback was that this made it difficult to give them assorted colours and properties, so I had to find some cheats for this too.

 

Evaluation

At the start of this project, I didn’t know anything about 3D graphics. After developing this abstract world in three.js from scratch, I can confidently say I am pleased with the outcome and what it has taught me. I consider Alternia a success, but I would not call it complete. There is a vast number of possibilities of new features that could be implemented in this world, and I feel I only scratched the surface.

The world is aesthetically appealing and could be something I’d want to see in a small adventure or exploration game. The low-poly graphics and random colour schemes work nicely, even if they are not realistic. As for content, it could be considered lacking. If I were to improve on this project, I would attempt to create a more content rich environment, with more places to visit, and even procedural generation (random parts of the world generated in real time).

References

http://codepen.io/chribbe/pen/LVwgJE - Water animation/tree placement

https://github.com/mattatz/THREE.Tree - three tree

http://stackoverflow.com/questions/30245990/how-to-merge-two-geometries-or-meshes-using-three-js-r71 - Merging geometries

https://japhr.blogspot.co.uk/2013/03/drawing-patterns-in-physijs-height.html - river trench

http://chandlerprall.github.io/Physijs/examples/heightfield.html - plane heightfield physi.js

https://github.com/Akimoto873/WebGL-Platformer/blob/master/Platform/WebContent/js/charController.js - camera look/move controls

https://learn.gold.ac.uk/mod/page/view.php?id=408665 - Random Flying

https://www.youtube.com/watch?v=P2q5M50x5Uw&t=4s - starfox 64 in threejs

https://humaan.com/blog/web-3d-graphics-using-three-js/ - low poly mountain image

https://github.com/josdirksen/learning-threejs – various geometries scene