Skip to content
This repository has been archived by the owner on Jul 21, 2022. It is now read-only.

A 3D interactive roller coaster designer.

License

Notifications You must be signed in to change notification settings

pfroud/rollercoaster-designer

Repository files navigation

Roller Coaster Designer

By Jonathan Bridge & Peter Froud. Final project for CM160: Introduction to Computer Graphics At UC Santa Cruz, fall 2015.

Screenshot of roller coaster designer Screenshot of roller coaster designer Screenshot of roller coaster designer

How to use

Our program lets the user design a roller coaster track from modular pieces.

To change the track that automatically loads, use one of the red X buttons at the bottom. The button with a blue background removes one piece, and the button with a red background deletes the entire track. Then, use the seven buttons at the top to add flat, sloped, or turn pieces. You can also use the shuffle button at the bottom to add a random sequence of curved track.

Press the play button at the bottom to start or stop the cart moving.

System requirements: web browser that supports WebGL. You can see if your browser supports WebGL by going to https://get.webgl.org/.

Implementation

The roller coaster you see is a Track instance which holds an array of Pieces. Every Piece holds information about its position, rotation, and the mesh to draw. The Track instance also manages insertion and deletion of Pieces.

We had a hard time finding a good way to store the constants for mesh dimensions. We started with a giant JSON file but ran into a problem: but we wanted to reference an object while still creating it, which JSON doesn't allow. For example, we wanted to do something like this:

{"down": {
		"size": {
			"x": 54.3057,
			"y": 54.3057,
			"z": 40.7995
		},
		"startOffset": {
			"y": down.size.y - 11.88,
		}
}}

which is invalid JSON. Amazingly, GitHub's syntax formatting tells us this.

Using Javascript "classes", we can do this:

TrackConst.prototype.down = function () {
    var down = new TrackType();
    down.size = {
        x: 54.3057,
        y: 54.3057,
        z: 40.7995
    };
    down.startOffset.y = down.size.y;
    return down;

which is what we want. That example is from scripts/constant.js.

We had to rush towards the end. When trying to implement the Cart moving along the track, we learned that arctangent from Javascript's Math class doesn't behave as expected. After a lot of ugly coding, we did eventually manage to get something that has a semblance of working. But the implementation is gross.

Classes

Not actually classes because JS is prototype-based This diagram shows, poorly, how the classes interact:

Diagram of Javascript classes

Track: the main class of the project

  • Holds an array of Pieces, which you see as a roller coaster track
  • Manages adding Pieces throughTrack.insertPiece(piece), where piece is either a single Piece object or an array of Pieces. Each Piece must be moved and rotated to lign up with the previous one.
  • Also manages deleting Pieces.
  • Location: scripts/Track.js

Piece: one track segment.

  • Knows its location, direction, dimensions, and how much pre- and post-correction must be made to make other Pieces fit.
  • Location: scripts/Piece.js

Support: generates the support beams beneath a track piece.

  • Basically makes a cylinder and moves it around just right.
  • Only called by Piece class.
  • Location: scripts/Support.js

TrackConst: A single class that holds all the constant data.

  • For each type of track, holds mesh's dimensions and how much pre- and post-correction must be made to make other Pieces fit.
  • Specifies where extra Supports go on curved pieces to make it look nice.
  • For turn or not-flat pieces, defines how the Cart animates over it.
  • Never accessed directly, only through global constant TRACK_TYPES which is an instance of TrackType().
  • Location: scripts/constant.js. You might be asking why some of our filenames are capitalized and some aren't. Because we're fundamentally bad people, that's why.

TrackType: Inner class to TrackConst. Should be called PieceType. Holds constants for each type of Piece.

  • Each type of Piece (e.g. FLAT_TO_UP) gets a TrackType which holds constants for that type. Then the constants are access through TRACK_TYPES.FLAT_TO_UP, for example.
  • Prevents code from being horrible, believe it or not.
  • Only used to make global constant TRACK_TYPES, which only happens in the constructor for TrackConst.
  • Location: scripts/constant.js

Gui: how the user interface buttons access the other classes.

  • Each button has its own object.
  • Accessed only by the global variable GUI.
  • Location: gui/gui.js

Other

Notable global variables:

  • TRACK: instance of Track() and the track displayed on the screen. Declared in Track.js.
  • SCALE: can change the size of pieces. Ultimately not needed, however we thought it’d be useful in early implementations. Declared in index.js.
  • SPEED: how fast the roller coaster moves across the track. Declared in Cart.js.
  • PLAY: boolean that tells the renderer whether or not to run the Cart animation.

Libraries used:

  • three.js: the big one. Abstracts WebGL drawing.
  • jquery: dependency of three.js.
  • dat.gui.js: helper GUI that we used when first implementing because it was easier than messing around with CSS every time we wanted to do something. No longer used, but kept in the library.
  • OrbitControls.js: three.js plugin to make the camera usable. View demo.

Other files of note:

  • index.html: project entry point, where everything is put in.
  • index.js: the initializer for three.js. Sets up things like camera, controls, ground plane, skybox, lighting, and renderer.
  • skybox.js: makes the skybox around the track, using a shader from a library that comes with three.js. Source.
  • Cart.js: the frankenstein’s monster that controls the car. Could be cleaned up a bunch. It’s ugly because we were rushed.

Novelties

We began by using 3D models from Rollercoaster Pre-fab by Adam W, but weren't really satisfied. We thought it would be better to have total control over the models.

We used Autodesk Inventor to model all our own track pieces. We had to jump through some hoops to get those models into the json format the three.js uses. From Inventor, we exported the model to a .dwg file, which we imported into a trial version of SketchUp Pro. From Sketchup we exported an .obj file, which could be converted using convert_obj_three.py which is included in three.js.

Modelling progression: tube, single strut, strut pattern, bend.

Screenshot of curved track in CAD

Screenshot of straight track in CAD

You can access all of the original and intermediate files in track 3D models folder.

About

A 3D interactive roller coaster designer.

Topics

Resources

License

Stars

Watchers

Forks

Languages